我在静态初始化中遇到崩溃(调试断言失败:VC ++ 2008中的CRT堆指针无效),我不确定我理解为什么。
我已经在static initialization fiasco阅读了关于C++ FAQ结束的所有内容,我认为我已经掌握了它 - 我不明白为什么会这样,或者为什么会这样一场惨败。
所以这就是情况(为简洁起见,省略了大多数非静态成员)。我有一个类,A,在A.h中定义:
class A {
public:
virtual ~A() { }
virtual void do_something();
};
然后,我有一个类C,它有一个嵌套类B,它是A的子类.C还包含一个B类私有静态成员:
class C {
public:
void do_the_C_thing();
private:
class B : public A {
public:
virtual void do_something();
};
static B my_personal_B;
};
最后,有C的实现文件C.cpp,其中包含my_personal_B的存储单元:
C::B my_personal_B;
C::C() {
}
C::do_the_C_thing() {
// [...]
my_personal_B.do_something();
// [...]
}
void C::B::do_something() {
// overridden do_something for C's private B class
}
这个模式对很多类都重复了,每个类都有一个从A继承的嵌套类。这几个代码修订版都运行得很完美,但是最近应用程序崩溃了这个特定的错误信息:
调试断言失败!
计划:
[删除] .EXE
文件:f:\ dd \ vctools \ crt_bld \ self_x86 \ crt \ src \ dbgheap.c
行:1511
表达式:_CrtIsValidHeapPointer(pUserData)
如果我点击调试,我会在C.cpp中显示该行,其中定义了静态成员。
这似乎不是静态惨败,因为没有静态引用my_personal_B,A和B都没有任何东西,只有默认构造函数,因此不可能引用其他一些尚未初始化的静态对象。我理解惨败的方式是当一个静态对象引用另一个尚未初始化的静态对象时发生。
然而,如果我将静态成员更改为初始化初始化方法,则崩溃似乎消失了。
所以问题是,为什么会崩溃?
答案 0 :(得分:2)
A类有虚拟功能。这意味着编译器会生成一个名为 vtable 的静态对象来保存指向成员函数的指针。因此,虽然您没有在类A中定义任何静态对象,但编译器必须这样做。 B类取决于vtable(对于A的虚拟析构函数,如果没有别的话)。显然,初始化代码现在尝试在构造A的vtable之前创建类型B的对象。
答案 1 :(得分:-1)
老兄,你为什么一开始就依赖静态初始化?你能说“设计错误”吗?
建议:
如果你不能改变设计,至少要确保设置一个标志“bInitialized”,这样相关的客户端可以检查你的对象是否实际被初始化,并且正常失败。
... IMHO