You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Original bug ID: 1994 Reporter: administrator Status: closed (set by @xavierleroy on 2006-06-17T09:56:17Z) Resolution: won't fix Priority: normal Severity: minor Category: ~DO NOT USE (was: OCaml general)
I stumbled on a rather nasty condition in Hashtbl that will cause a
stack overflow with a bit bigger than normal data amounts.
A snippet that demonstrates this:
,----
| let tbl = Hashtbl.create 10 in
| for i = 0 to 100000 do
| Hashtbl.add tbl 1 "test"
| done;;
`----
The bug is as follows - hash table resizing has a recursive function
called to migrate a single bucket to the new table and it is not tail
recursive.
Here's the bit of code:
,----[ hashtbl.ml ]
| let resize hashfun tbl =
| let odata = tbl.data in
| let osize = Array.length odata in
| let nsize = min (2 * osize + 1) Sys.max_array_length in
| if nsize <> osize then begin
| let ndata = Array.create nsize Empty in
| let rec insert_bucket = function
| Empty -> ()
| | Cons(key, data, rest) ->
| insert_bucket rest; (* preserve original order of elements *)
| let nidx = (hashfun key) mod nsize in
| ndata.(nidx) <- Cons(key, data, ndata.(nidx)) in
| for i = 0 to osize - 1 do
| insert_bucket odata.(i)
| done;
| tbl.data <- ndata;
| end
`----
In here, insert_bucket obviously isn't tail recursive.
So what it means is that if even a rather meager amount of values
happens to get stuffed in the same hash bucket, it will cause a
stack overflow.
I ran into this while using some of the standard bits in OCaml that
internally used a Hashtbl - so this ended up as a real and actual
problem.
-- Naked
The text was updated successfully, but these errors were encountered:
I stumbled on a rather nasty condition in Hashtbl that will cause a
stack overflow with a bit bigger than normal data amounts.
[...]
The bug is as follows - hash table resizing has a recursive function
called to migrate a single bucket to the new table and it is not tail
recursive.
Thank you for your bug report. After careful consideration, we have
decided that a program exhibiting this behaviour is broken.
Instead of hiding the bug and degrading the performance catastrophically,
we think it's better to expose the bug (for example by triggering a stack
overflow). Hence, we will not try to fix this "problem" in Hashtbl.
I ran into this while using some of the standard bits in OCaml that
internally used a Hashtbl - so this ended up as a real and actual
problem.
This is interesting. I know this reply is very late, but can you still
give us more details about which part of OCaml, and under what
circumstances you found this problem?
Original bug ID: 1994
Reporter: administrator
Status: closed (set by @xavierleroy on 2006-06-17T09:56:17Z)
Resolution: won't fix
Priority: normal
Severity: minor
Category: ~DO NOT USE (was: OCaml general)
Bug description
Full_Name: Nuutti Kotivuori
Version: 3.07+7 (2003-12-17)
OS: Debian GNU/Linux
Submission from: aka.pp.htv.fi (213.243.183.115)
I stumbled on a rather nasty condition in Hashtbl that will cause a
stack overflow with a bit bigger than normal data amounts.
A snippet that demonstrates this:
,----
| let tbl = Hashtbl.create 10 in
| for i = 0 to 100000 do
| Hashtbl.add tbl 1 "test"
| done;;
`----
The bug is as follows - hash table resizing has a recursive function
called to migrate a single bucket to the new table and it is not tail
recursive.
Here's the bit of code:
,----[ hashtbl.ml ]
| let resize hashfun tbl =
| let odata = tbl.data in
| let osize = Array.length odata in
| let nsize = min (2 * osize + 1) Sys.max_array_length in
| if nsize <> osize then begin
| let ndata = Array.create nsize Empty in
| let rec insert_bucket = function
| Empty -> ()
| | Cons(key, data, rest) ->
| insert_bucket rest; (* preserve original order of elements *)
| let nidx = (hashfun key) mod nsize in
| ndata.(nidx) <- Cons(key, data, ndata.(nidx)) in
| for i = 0 to osize - 1 do
| insert_bucket odata.(i)
| done;
| tbl.data <- ndata;
| end
`----
In here, insert_bucket obviously isn't tail recursive.
So what it means is that if even a rather meager amount of values
happens to get stuffed in the same hash bucket, it will cause a
stack overflow.
I ran into this while using some of the standard bits in OCaml that
internally used a Hashtbl - so this ended up as a real and actual
problem.
-- Naked
The text was updated successfully, but these errors were encountered: