Hi Thomas,
On 2011-09-27, at 19:30, Thomas Fischbacher wrote:
> 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.
That's the key.
> if works
> then (get_ftag "funny",get_rtag "funny")
> else (Ftag "funny", Rtag (ref "funny"))
> in
In this expression, you have four interesting subexpressions. Three of
them involve calling some function with "funny" as argument, and these
functions allocate values that point to the "funny" string. These values
are heap-allocated and behave as you expect.
The fourth one is (Ftag "funny"). This is a constant expression and its
evaluation does not allocate in the heap. Since it's constant, it's
allocated once by the compiler, and every time you execute this code
it's the same value that is returned.
In byte-code it's still allocated in the heap, but at load-time, and
a reference to it is hidden in the closure of the enclosing function.
Hence, it never gets deallocated:
> $ ocaml gc_bug.ml
> Removing ref 'funny'
> ht_str entries: 1 ht_ref entries: 0
You don't get the "Removing str 'funny'" message because the value
stays alive throughout program execution.
In native code, it's even more optimized: the value is "allocated" at
compile time as constant data outside the heap. Hence, you can't even
register a finalizer for it:
> $ ocamlopt -o gc_bug gc_bug.ml
>
> $ ./gc_bug
> Fatal error: exception Invalid_argument("Gc.finalise")
Only heap data can be finalized.
So you have to be aware of the difference between (get_ftag "funny") and
(Ftag "funny") because they don't have exactly the same semantics: a call
to get_ftag is guaranteed to allocate a new block each time.
-- Damien
--
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