On Friday, 17 September 2021 at 06:27:40 UTC, frame wrote:
> Thanks, I'm just careful with casting.
Does it really allocate from a literal if it's used on the stack only? Is -vgc
switch reliable?
looks to me like it calls
// object
private U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
{
if (__ctfe)
return _dupCtfe!(T, U)(a);
import core.stdc.string : memcpy;
auto arr = _d_newarrayU(typeid(T[]), a.length);
memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
return *cast(U[]*) &arr;
}
->
// rt.lifetime
extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow @weak
{
...
auto info = __arrayAlloc(size, ti, tinext);
...
}
->
// rt.lifetime
BlkInfo __arrayAlloc(size_t arrsize, const scope TypeInfo ti, const TypeInfo tinext) nothrow pure
{
...
auto bi = GC.qalloc(padded_size, attr, tinext);
...
}
->
// gc.impl.conservative.gc
BlkInfo qalloc( size_t size, uint bits, const TypeInfo ti) nothrow
{
if (!size)
{
return BlkInfo.init;
}
BlkInfo retval;
retval.base = runLocked!(mallocNoSync, mallocTime, numMallocs)(size, bits, retval.size, ti);
if (!(bits & BlkAttr.NO_SCAN))
{
memset(retval.base + size, 0, retval.size - size);
}
retval.attr = bits;
return retval;
}
which you can also follow in an objdump. Conclusion: -vgc is missing this GC allocation.
To stack-allocate a mutable copy of a string literal go with
@safe @nogc nothrow unittest {
enum S = "hello world";
char[S.length+1] s1 = S;
char* s2 = &s1[0];
// Normally you'd expect s1.ptr[s1.length] here,
// but the '\0' byte is explicitly part of s1 due to length+1 above.
assert(s1[s1.length-1] == '\0');
(() @trusted {
import core.stdc.stdio : puts;
import std.string : fromStringz;
puts(s2);
assert(s2.fromStringz == S);
})();
}