Dear Camels,
The example below shows GC behaviour which in my view is somewhat
weird: I am building two very similar sorts of hash tables that map
variant types to strings. The parameter "works" (which gets passed
through from the "demo" to the "setup" function) allows one to choose,
when calling the script, whether it behaves properly or shows weird
behaviour.
For Rtag, inlining get_rtag does not make a difference, but for Ftag,
inlining the get_ftag call breaks things both with the interpreter and
compiler, but in different ways.
So... my question is: is there a documented reliable way to avoid this
sort of funny behaviour?!?
=================================
type funny_tag = Ftag of string;;
type funny_ref = Rtag of string ref;;
let get_ftag s = Ftag s;;
let get_rtag s = Rtag (ref s);;
let fin_str ht k =
let Ftag s = k in
let () = Printf.printf "Removing str '%s'\n%!" s in
Hashtbl.remove ht k
;;
let fin_ref ht k =
let Rtag rs = k in
let () = Printf.printf "Removing ref '%s'\n%!" !rs in
Hashtbl.remove ht k
;;
let setup works =
let ht_str = Hashtbl.create 17 in
let ht_ref = Hashtbl.create 17 in
let (funny_str, funny_ref) =
if works
then (get_ftag "funny",get_rtag "funny")
else (Ftag "funny", Rtag (ref "funny"))
in
(* Note that they keys used below are equal but not identical to the
entities above *)
let () = Hashtbl.add ht_str (Ftag "funny") "situation" in
let () = Hashtbl.add ht_ref (Rtag (ref "funny")) "situation" in
let () = Gc.finalise (fin_str ht_str) funny_str in
let () = Gc.finalise (fin_ref ht_ref) funny_ref in
((ht_str,ht_ref),(funny_str,funny_ref))
;;
let left (p,q) = p;;
let demo works =
let (ht_str,ht_ref) = left (setup works) in
(* Note that I drop the references on the keys that have finalizers
registered. *)
let () = Gc.full_major () in
let () = Gc.compact () in
Printf.printf "ht_str entries: %d ht_ref entries: %d\n%!"
(Hashtbl.length ht_str) (Hashtbl.length ht_ref)
;;
let () = demo (Array.length Sys.argv > 1 && Sys.argv.(1) = "magic");;
(* === Behaviour ===
$ ocaml gc_bug.ml
Removing ref 'funny'
ht_str entries: 1 ht_ref entries: 0
$ ocaml gc_bug.ml magic
Removing ref 'funny'
Removing str 'funny'
ht_str entries: 0 ht_ref entries: 0
$ ocamlopt -o gc_bug gc_bug.ml
$ ./gc_bug
Fatal error: exception Invalid_argument("Gc.finalise")
$ ./gc_bug magic
Removing ref 'funny'
Removing str 'funny'
ht_str entries: 0 ht_ref entries: 0
$ ocaml
Objective Caml version 3.12.0
#
$ uname -prs
FreeBSD 9.0-BETA3 amd64
============ *)
=================================
--
best regards,
Thomas Fischbacher
[email protected]
--
Caml-list mailing list. Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs