www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - toStringz note about keeping references

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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
next sibling parent "Kagamin" <spam here.lot> writes:
Probably a bug in GC, immutable data should be collected if not 
needed.
Oct 15 2012
prev sibling parent "Kagamin" <spam here.lot> writes:
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