* [Caml-list] Problem with GC and custom blocks @ 2003-03-25 10:31 Falk Hueffner 2003-03-25 18:39 ` Damien Doligez 0 siblings, 1 reply; 3+ messages in thread From: Falk Hueffner @ 2003-03-25 10:31 UTC (permalink / raw) To: caml-list Hi, I'm having trouble with the GC destroying my custom blocks, although it looks like I have properly protected them. Unfortunately, I cannot reproduce it with a small testcase. Here's part of the source and its output: static inline value alloc_graph(unsigned n, unsigned vertex_bits, unsigned edge_bits) { value r = alloc_custom((struct custom_operations *) &graph_ops, 1 << 16, // huge value to trigger bug earlier 0, 1); long *l = Data_custom_val(r); for (int i = 0; i < 32/4; ++i) l[i] = 0xefbeadde; dumpbytes(r, 32, __PRETTY_FUNCTION__); return r; } static inline value clone_graph(const struct graph *g) { dumpbytes(((char*) g) - 4, 32, __PRETTY_FUNCTION__ " in"); value gv = alloc_graph(g->n, g->vertex_bits, g->edge_bits); dumpbytes(((char*) g) - 4, 32, __PRETTY_FUNCTION__ " post"); make_copy(Data_custom_val(gv), g); dumpbytes(gv, 32, __PRETTY_FUNCTION__ " out"); return gv; } // set_connected: graph -> int -> int -> graph value set_connected_c(value gv, value iv, value jv) { fprintf(stderr, "protecting %p\n", gv); CAMLparam3(gv, iv, jv); dumpbytes(gv, 32, __PRETTY_FUNCTION__); const struct graph *gin = Data_custom_val(gv); ulong i = Long_val(iv); ulong j = Long_val(jv); CAMLlocal1(goutv); goutv = clone_graph(gin); struct graph *gout = Data_custom_val(goutv); set_connected(gout, i, j); dumpbytes(goutv, 32, __PRETTY_FUNCTION__ " out"); CAMLreturn(goutv); } [...] protecting 0x400c8fec 0x400c8fec set_connected_c 80 e9 07 08 08 00 01 01 00 00 00 00 00 00 00 00 0x400c8fec clone_graph in 80 e9 07 08 08 00 01 01 00 00 00 00 00 00 00 00 <>allocated_words = 32790 extra_heap_memory = 0u amount of work to do = 134084u ordered work = 0 words computed work = 221332 words Sweeping 221332 words $FL size at phase change = 168445 Estimated overhead = 1000000% Automatic compaction triggered. Starting new major GC cycle Marking 2147483647 words Sweeping 2147483647 words Measured overhead: 137% Compacting heap... Shrinking heap to 2976k bytes Shrinking heap to 2728k bytes Shrinking heap to 2480k bytes done. 0x400ed004 alloc_graph 80 e9 07 08 de ad be ef de ad be ef de ad be ef 0x400c8fec clone_graph post 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 So 0x400c8fec gets mangled, although I protected it. Did I do something obvious wrong? Or are there any known bugs in the GC? Any other suggestions how to track this down? I'd be really grateful even for a workaround... I'm using ocamlopt 3.06 on i386 Linux, with gcc 3.2. Falk ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Caml-list] Problem with GC and custom blocks 2003-03-25 10:31 [Caml-list] Problem with GC and custom blocks Falk Hueffner @ 2003-03-25 18:39 ` Damien Doligez 2003-03-25 18:51 ` Falk Hueffner 0 siblings, 1 reply; 3+ messages in thread From: Damien Doligez @ 2003-03-25 18:39 UTC (permalink / raw) To: Falk Hueffner; +Cc: caml-list On Tuesday, March 25, 2003, at 11:31 AM, Falk Hueffner wrote: > I'm having trouble with the GC destroying my custom blocks, although > it looks like I have properly protected them. Unfortunately, I cannot > reproduce it with a small testcase. You seem to misunderstand the purpose of the CAMLparam and CAMLlocal macros. The GC is not destroying your custom blocks, it is moving them. Because it is moving them, it has to update all pointers to them. Hence, it is the *pointers* (in fact, the local variables that contain these pointers) that need to be "protected". > static inline value alloc_graph(unsigned n, > unsigned vertex_bits, unsigned edge_bits) > { > value r = alloc_custom((struct custom_operations *) &graph_ops, > 1 << 16, // huge value to trigger bug earlier > 0, 1); > long *l = Data_custom_val(r); > for (int i = 0; i < 32/4; ++i) > l[i] = 0xefbeadde; > dumpbytes(r, 32, __PRETTY_FUNCTION__); > return r; > } No problem here. Note that alloc_graph calls an allocation function, and thus may move blocks around. > static inline value clone_graph(const struct graph *g) { > dumpbytes(((char*) g) - 4, 32, __PRETTY_FUNCTION__ " in"); > > value gv = alloc_graph(g->n, g->vertex_bits, g->edge_bits); > dumpbytes(((char*) g) - 4, 32, __PRETTY_FUNCTION__ " post"); > > make_copy(Data_custom_val(gv), g); > dumpbytes(gv, 32, __PRETTY_FUNCTION__ " out"); > return gv; > } Here, you have a problem if g is a pointer into the heap, because you call alloc_graph, which may move heap blocks. > // set_connected: graph -> int -> int -> graph > value set_connected_c(value gv, value iv, value jv) { > fprintf(stderr, "protecting %p\n", gv); > CAMLparam3(gv, iv, jv); > dumpbytes(gv, 32, __PRETTY_FUNCTION__); > > const struct graph *gin = Data_custom_val(gv); > ulong i = Long_val(iv); > ulong j = Long_val(jv); > CAMLlocal1(goutv); > goutv = clone_graph(gin); > struct graph *gout = Data_custom_val(goutv); > > set_connected(gout, i, j); > dumpbytes(goutv, 32, __PRETTY_FUNCTION__ " out"); > > CAMLreturn(goutv); > } And here you trigger the problem by passing Data_custom_val(gv) as argument to clone_graph. What you should do is: 1. modify clone_graph to take a parameter of type "value" 2. protect this parameter with CAMLparam1 Even if another copy of the same address is protected in "set_connected_c" under the name of "gv", you still need to protect it under its new name in clone_graph, so the GC will be able to update both copies when it moves the data. Also, note that you cannot protect an infix pointer (a pointer that points inside a block instead of pointing to its head). That makes Data_custom_val rather error-prone and you should avoid storing its result in a variable or passing it as argument to functions that can allocate in the Caml heap. > So 0x400c8fec gets mangled, although I protected it. Did I do > something obvious wrong? Or are there any known bugs in the GC? Any > other suggestions how to track this down? I'd be really grateful even > for > a workaround... Please let me know if this helps. -- Damien ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Caml-list] Problem with GC and custom blocks 2003-03-25 18:39 ` Damien Doligez @ 2003-03-25 18:51 ` Falk Hueffner 0 siblings, 0 replies; 3+ messages in thread From: Falk Hueffner @ 2003-03-25 18:51 UTC (permalink / raw) To: Damien Doligez; +Cc: caml-list Damien Doligez <Damien.Doligez@inria.fr> writes: > What you should do is: > 1. modify clone_graph to take a parameter of type "value" > 2. protect this parameter with CAMLparam1 > > Even if another copy of the same address is protected in > "set_connected_c" under the name of "gv", you still need to protect > it under its new name in clone_graph, so the GC will be able to > update both copies when it moves the data. > > Please let me know if this helps. It helps. It's actually pretty obvious now that I know it, I was just somehow fixed to the idea that the GC considered the object dead erraneously, and did not consider moving... Thanks! -- Falk ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2003-03-25 18:51 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-03-25 10:31 [Caml-list] Problem with GC and custom blocks Falk Hueffner 2003-03-25 18:39 ` Damien Doligez 2003-03-25 18:51 ` Falk Hueffner
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox