toStringz note about keeping references

Andrej Mitrovic andrej.mitrovich at gmail.com
Sun Oct 14 14:38:48 PDT 2012


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.


More information about the Digitalmars-d-learn mailing list