pochodzi z this question, mam ten mały F kod # (github) do generowania wartości losowych według rozkładu normalnego:przepełnienie stosu mimo położenia połączeń ogon, ale tylko w wersji 64-bitowej
// val nextSingle : (unit -> float32)
let nextSingle =
let r = System.Random()
r.NextDouble >> float32
// val gauss : (float32 -> float32 -> seq<float32>)
let gauss mean stdDev =
let rec gauss ready = seq {
match ready with
| Some spare ->
yield spare * stdDev + mean
yield! gauss None
| _ ->
let rec loop() =
let u = nextSingle() * 2.f - 1.f
let v = nextSingle() * 2.f - 1.f
let s = pown u 2 + pown v 2
if s >= 1.f || s = 0.f then loop() else
u, v, s
let u, v, s = loop()
let mul = (*)(sqrt(-2.f * log s/s))
yield mul u * stdDev + mean
yield! mul v |> Some |> gauss
}
gauss None
wydaje mi się, że to powinno się tylko wywoływać w pozycji wywołania końcowego, ergo nigdy nie powodować StackOverflowException
, gdy TCO jest włączone. Ale to ma podczas pracy z 64-bitowym 642-bitowym. To nie ma wartości podczas uruchamiania 32-bitowego (tj. "Preferuj 32-bitowe" w ustawieniach projektu).
Używam .NET Framework 4.5.2 i F # 4.4.0.0.
Czy ktoś może wyjaśnić, co jest przyczyną problemu?
Którą wersję .NET używasz? – Roujo
Znalazłem te artykuły, mówiąc o optymalizacji połączeń ogonowych [przy użyciu .NET 2.0] (https://blogs.msdn.microsoft.com/davbr/2007/06/20/tail-call-jit-conditions/) vs [using. NET 4.0] (https://blogs.msdn.microsoft.com/clrcodegeneration/2009/05/11/tail-call-improvements-in-net-framework-4/), może mogą pomóc. – Roujo
Również jakiej wersji F # używasz? Używam F # 4 i kiedy debuguję, w ogóle nie widzę stosu. Zdemontowałem kod IL i wygląda na to, że kod generowany przez F # 4 nie powinien być stackoverflow. – FuleSnabel