d复制构造器问题
原文
自DMD2.101.0起,以下程序成功编译并运行完成:
struct S
{
this(ref S)
{
assert(0);
}
}
void main()
{
S[] a = [ S() ];
auto p = a.ptr;
// 直到重新分配,追加
while (a.ptr == p)
a ~= S(); // 无断定
}
重新分配数组时,程序应该在运行时断定,但是没有,因为没有调用数组元素的复制构造器.
如果更改复制构造器为postblit('this(this)'),则程序期望的在运行时断定.
另见影响了.dup和.idup的#20879问题.
更清晰:
import std.typecons;
import std.sumtype;
import std.stdio;
import core.memory;
void fun(RefCounted!string foo) {
SumType!( RefCounted!(string) )[] foo_storage;
foo_storage ~= SumType!( RefCounted!(string) )(foo);
foo_storage ~= SumType!( RefCounted!(string) )(foo); // 再分配,但未复制
foo_storage = null;
}
void clobber()
{
int[1000] x = 0x123456;
}
void main(){
RefCounted!( string ) foo = RefCounted!( string )("哈哈");
fun(foo);
clobber();
GC.collect(); // 收集GC中已有项
writeln(foo);
}
这里:
1.用sumtype创建元素数组.
2.数组不能容纳第二个元素,所以重新分配.然而,没有调用SumType的复制构造器.因此'foo'的引用计数为3,但实际有4个引用(单元素数组,双元素数组,及栈上的原始foo).
3.clobber确保栈不指向数组.
4.GC.垃集清理3个foo元素,计数减少到0并释放.
5.writeln现在正在写垃圾.在我系统上,它只是向屏幕上喷出了随机内存数字.
a~=S()不应调用复制构造器或postblit,因为应该在数组内原位创建新追加的元素.
问题在,重新分配时复制数组.正确调用了postblit,但未正确调用复制构造器.
struct S
{
this(this)
{
writeln("pblit");
}
}
void main()
{
S[] a = [ S() ];
auto p = a.ptr;
// 直到重新分配,追加
while (a.ptr == p)
{
writeln("loop");
a ~= S(); // 无断定
}
}
要么向TypeInfo添加更多特殊成员,要么修改勾挂,以便可向运行时解释如何调用复制构造器.
浙公网安备 33010602011771号