I came across this while doing work on std.typecons.Unique (see https://github.com/D-Programming-Language/phobos/pull/3139). Any class that accesses a local context seems to segfault when emplaced. A minimal test case follows:
import core.stdc.stdlib : malloc, free;
import std.conv : emplace;
import std.traits : classInstanceAlignment;
void main()
{
int created;
int destroyed;
class Foo {
this() { ++created; }
~this() { ++destroyed; }
}
immutable size_t size = __traits(classInstanceSize, Foo);
void* m = malloc(size);
assert(m);
Foo f = emplace!Foo(m[0 .. size]);
assert(created == 1);
f.destroy();
free(m);
assert(destroyed == 1);
}
The problem doesn't seem to be the amount of memory I am allocating, given that it makes it past the testEmplaceChunk call in emplace. A stack trace from GDB is as follows:
Program received signal SIGSEGV, Segmentation fault.
0x000000000042afd4 in wat.main().Foo.this() (this=0x66d450) at wat.d:10
10 this() { ++created; }
(gdb) where
#0 0x000000000042afd4 in wat.main().Foo.this() (this=0x66d450) at wat.d:10
#1 0x000000000042b167 in std.conv.emplace!(wat.main().Foo).emplace(void[]) (chunk=...)
at /home/mrkline/src/dlang/phobos/std/conv.d:5005
#2 0x000000000042af76 in D main () at wat.d:19
where the relevant line in conv.d is
result.__ctor(args);
This was seen on 2.067 and the current master for dmd and phobos as of 2015-04-03 01:20 PST.
Comment #1 by mkline.on.d — 2015-04-05T22:50:31Z
I just noticed that if you try to `new` a context-aware class or struct outside that context, you get a nice compiler warning indicating that you cannot do so. Can we, via template magic or something similar, issue a similar error when trying to emplace one?
Comment #2 by aliloko — 2016-10-14T21:22:04Z
Also rediscovered this bug.
Comment #3 by nick — 2017-05-08T12:54:15Z
(In reply to Matt Kline from comment #1)
> Can we, via template magic or something similar, issue a
> similar error when trying to emplace one?
I think so, I'm working on a PR. Basically the initializer args have to contain a type that has a usable context pointer. The remaining case is:
S s;
emplace(&s, S.init);
In solving that, I think disallowing rvalue initializers is too strict (as they could have a valid context pointer). Perhaps this can be detected at runtime instead.