Я в настоящее время сталкиваюсь с проблемой с VS08. Я получил следующую (упрощенную) структуру классов:
class CBase
{
public:
virtual void Func() = 0;
};
class CDerived : public CBase
{
public:
void Func();
};
Этот код работает нормально в Release Mode, но когда я пытаюсь запустить Debug Build, он мгновенно падает на new CDerived
,
Дальнейший анализ привел меня к тому, что я смог определить местонахождение аварии. Это происходит сбой в CBase :: CBase (сгенерированный компилятором конструктор). Точнее он падает на 04AE46C6 mov dword ptr [eax],offset CBase::
vftable ‘(505C2CCh) `.
Есть какие-нибудь подсказки? Режим выпуска в порядке, но я не могу правильно отладить его.
Режим выпуска в порядке
Нет, похоже, все в порядке. Я думаю, что в отладке память как-то перезаписывается. Поскольку нет способа узнать только из кода, который вы разместили, вот что вы можете сделать.
Я предполагаю, что вы создаете объект где-то с:
CBase* p = new CDerived;
или похожие. В режиме отладки установите точка останова памяти в p
расположение. Вы можете установить его для контроля 4 байта. Visual C ++ (как и большинство компиляторов) будет сохранять vfptr первым в классе, поэтому эта точка останова будет отслеживать, перезаписано ли это местоположение. Если точка останова достигнута до того, как вы вызовете функцию, в которой происходит сбой, это ваша проблема (и стек вызовов покажет вам, почему он перезаписан).
Причин может быть много — вы могли бы переполнить некоторую память и перезаписать объект (как предположил Эрик) — версия выпуска могла бы разрешить вызов напрямую, чтобы предотвратить издержки динамической отправки, и это объяснило бы, почему это не происходит сбой.
Также может быть, что вы звоните delete
на объекте и отладочной версии фактически обнуляет память, в то время как версия выпуска не делает. Невозможно сказать, просто из этого.
Немного постинга здесь, но я хочу кое-что сделать для будущих посетителей …
Как уже говорили другие, это, вероятно, проблема с повреждением памяти или свободным повторным использованием. Вы не должны предполагать, что это была ошибка компилятора только потому, что вы смогли устранить сбой, изменив настройки компилятора или переставив код. Если это ошибка, связанная с повреждением, то вы, вероятно, сделали, чтобы переместить повреждение в некоторую память, которая не вызывает сбой вашей программы — не в вашей текущей сборке, в вашей текущей ОС & архитектура, во всяком случае.
Для достижения ваших непосредственных потребностей может быть достаточно просто добраться до точки отказа, но в то же время вы не научились избегать какой-либо практики, побудившей вас сначала написать ошибку. Среди инженеров существует давняя пословица и, вероятно, немало других дисциплин:
«То, что уходит само собой, может вернуться само собой».
Это может быть одна из самых верных и важных пословиц в любой форме техники. Если вы сами не видели, как жук погиб, вы всегда должны беспокоиться об этом. Это должно беспокоить вас, глубоко. Ошибка, вероятно, все еще там, в ожидании ночи вашего следующего рубежа, прежде чем она вновь возродится.
Лучиан Григоре дал хороший совет по поиску реальной проблемы с точкой останова памяти.