digitalmars.D.learn - toStringz note about keeping references
- Andrej Mitrovic (62/62) Oct 14 2012 Docs of toStringz:
Docs of toStringz: [begin] pure nothrow immutable(char)* toStringz(string s); Returns a C-style zero-terminated string equivalent to s. s must not contain embedded '\0''s as any C function will treat the first '\0' that it sees as the end of the string. If s.empty is true, then a string containing only '\0' is returned. Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may go away during a garbage collection cycle and cause a nasty bug when the C code tries to use it. [end] Why is this note put here? It makes sense for char*, but I don't think it makes sense to put this in the toStringz docs because this function operates on immutable data and returns immutable data, so this rule doesn't apply to it. toStringz takes a string (immutable(char)[]), and the GC will not reclaim immutable data until app exit. For example: import std.stdio; import std.string; import core.memory; void test() { string x = "foo".idup; const(char)* str = toStringz(x); writefln("\n-- Address: %s-- \n", str); } void main() { test(); GC.collect(); writeln("\n --Collect Done-- \n"); } If you build druntime with -debug=PRINTF and run the above (you will need git HEAD to compile druntime like that): -- Address: 972FA0-- GC.fullCollect() processing GC Marks, 8c1824 cache entry 0 has base ptr 0 size 0 flags 0 cache entry 1 has base ptr 0 size 0 flags 0 cache entry 2 has base ptr 0 size 0 flags 0 cache entry 3 has base ptr 0 size 0 flags 0 cache entry 4 has base ptr 0 size 0 flags 0 cache entry 5 has base ptr 0 size 0 flags 0 cache entry 6 has base ptr 0 size 0 flags 0 cache entry 7 has base ptr 0 size 0 flags 0 collecting 00971FE0 collecting 00972FB0 collecting 00972FC0 collecting 00972FD0 collecting 00972FE0 collecting 00972FF0 --Collect Done-- processing GC Marks, 0 collecting 00972FA0 "00972FA0" was only reclaimed upon app exit, so there's no fear that a GC cycle will destroy immutable data which might be pointed to in a C function. So shouldn't that char* note be put somewhere else? E.g. in the interfacing with C section maybe.
Oct 14 2012
Probably a bug in GC, immutable data should be collected if not needed.
Oct 15 2012
It's also possible that if a function reserves stack without clearing it, some old values may remain in the stack which were passed to other functions, so you'll have false pointers.
Oct 15 2012