Я получаю сбой (ошибка утверждения отладки: неверный указатель кучи CRT в VC++ 2008) при статической инициализации, и я не уверен, что понимаю, почему.
Я прочитал все о статической инициализации. фиаско в 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 не имеют ничего, кроме конструкторов по умолчанию, и поэтому не могут ссылаться на какой-то другой, еще не инициализированный статический объект. Насколько я понял фиаско, это произошло, когда один статический объект ссылался на другой, еще не инициализированный статический объект.
Тем не менее, если я изменю статический член на метод инициализации при первом использовании, сбой, похоже, исчезнет.
Так вот вопрос, почему этот сбой?