考虑:
struct V {
V(int i) {
std::cout << "initialized v" << '\n';
}
};
struct A {
A() {
std::cout << "initialized a" << '\n';
}
};
struct B : virtual V, virtual A {
B(int i) :V{i} {
std::cout << "initialized b" << '\n';
}
};
class C : virtual V, virtual A {
public:
C(int i) : V{i} {
std::cout << "initialized c" << '\n';
}
};
class D : virtual public B, virtual public C {
public:
D(int i, int j) :V{i}, B{i}, C{j} {
std::cout << "initialized d" << '\n';
}
};
如果我在main()中初始化D,就像这样:
int main() {
D* d = new D{3,3}; //ok
B* b = new D{3,3}; //ok
C* c = new D{3,3}; //undefined
delete d;
delete b;
delete c;
}
但如果我使用工厂,就像这样:
C* factory() {
return new D{3,3};
}
int main() {
factory(); //ok
}
当我在main()中初始化D到C时,我无法弄清楚它为什么会导致未定义的行为,但在使用其他函数时工作正常。 C有什么问题?它和B一样吗?
编辑:所以我认为我的代码在this demo上正常运行。如果我的代码没有问题,我的开发环境是否有问题?我使用最新的mingw-w64和eclipse CPP。
答案 0 :(得分:2)
你正在寻找所有错误地方的不确定性。
delete b;
delete c;
两行都通过指向基类(D
或B*
)而没有虚析构函数的指针删除派生类对象(C*
)来调用未定义的行为。给他们一个(例如,将virtual ~V() = default;
添加到V
),崩溃就会消失。
这就是为什么验证您在此处发布的代码重现编译和运行时遇到的崩溃的重要性。如果完整代码在开头可用,有人可能会在不到5分钟的时间内发现问题。相反,我们花了45分钟试图重现问题。