我正在尝试使用手动内存管理从昂贵的对象管理生命周期,在我的单元测试期间,我似乎在本示例中destroy(bar)
下面的主方法中使用访问冲突导致程序崩溃。
这是我遇到访问冲突问题的最小例子。
我不明白出了什么问题。
class Foo { int i;}
struct Bar
{
Foo _p;
this(Foo foo)
{
_p = foo;
}
~this() {
import core.stdc.stdlib : free;
if (_p !is null)
{
destroy(_p);
free(cast(void*)_p);
_p = null;
}
}
}
void main(string[] argv)
{
import std.conv;
import core.stdc.stdlib;
Foo foo = emplace(cast(Foo) malloc(Foo.sizeof));
Bar bar = Bar(foo);
destroy(bar);
}
答案 0 :(得分:5)
请注意,destroy将_p设置为null为“你...”,这意味着你永远不会释放它。改为Foo tmp = _p; destroy(_p); free(cast(void*) tmp);
或类似的东西,所以你要在destroy调用之外保留一个临时的引用副本。这不是导致你崩溃的原因,那只是内存泄漏。
崩溃是因为,Foo.sizeof
类是引用的大小,而不是实例的大小。对于课程,您需要malloc(__traits(classInstanceSize, Foo))
。文档提到这是其先决条件之一:http://dpldocs.info/experimental-docs/std.conv.emplace.3.html
这导致你的崩溃,因为你没有为vtable分配足够的空间(因此也可能会损坏内存,因为你的演员阵容导致了类型检查!)。我会malloc并切片而不是投射它。
// malloc the instance size then slice it to get a type-safe representation
void[] memory = malloc(__traits(classInstanceSize, Foo))[0 .. __traits(classInstanceSize, Foo)];
emplace!Foo(memory); // emplace a new one in that memory
在将类引用传递给该结构时,您也应该小心,因为如果它没有被malloced或者如果有另一个引用,则会出现悬空问题。