Что может заставить указатель VTable быть 0xdddddddd в сборке отладки Win32? - PullRequest
9 голосов
/ 19 апреля 2011

Я отлаживаю дефект и сузил его до указателя vtable для объекта, являющегося 0xdddddddd. Этот ответ указывает, что в отладочных сборках Win32 это специальное значение обычно устанавливается для мертвой памяти или памяти, которая была удалена.

Обратите внимание, что указатель сам по себе выглядит допустимым, это просто указатель vtable , то есть 0xdddddddd.

Вот фрагмент кода:

std::list<IMyObject*>::const_iterator it;
for (it = myObjects.begin(); it != myObjects.end(); ++it)
{
    IMyObject* pMyObject = *it;
    if (pMyObject == 0)
        continue;

    pMyObject->someMethod(); // Access violation     
}

Если я нарушу строку нарушения доступа исмотрите pMyObject, я вижу, что сам pMyObject имеет действительный адрес (0x08ede388), но член __vfptr недействителен (0xdddddddd).

Некоторые примечания:

  • Это однопоточное приложение, так что это, скорее всего, не проблема гонки или мьютекса.
  • Кажется, что нет никаких очевидных проблем, таких как удаление объекта дальше вверх по стеку вызовов додоступ к нему.
  • Эта проблема, по-видимому, воспроизводима только на сервере Windows 2008, но не на Windows 7.

Любые предложения о том, как отладить это дальше?

Ответы [ 4 ]

9 голосов
/ 19 апреля 2011

Вы используете указатель после того, как он был выпущен. Получите трассировку стека от точки останова в деструкторе, чтобы увидеть, что ее удаляет. Или еще лучше, используйте shared_ptr <>, чтобы избежать проблемы.

1 голос
/ 29 мая 2018

Хорошо, ничего себе, так что я программировал на c ++ годами и никогда не обнаруживал этого до сих пор ... На самом деле магические числа / магические значения отладки , которые вы можете посмотреть, чтобы увидеть, что происходит ваши сырые указатели при отладке!

См. Здесь: Каковы представления распределения памяти в Visual Studio C ++?

и здесь: https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_debug_values

1 голос
/ 21 ноября 2013

Если pMyObject-> someMethod () в конечном итоге завершает изменение списка myObjects, это делает недействительным любой из текущих итераторов.

Кроме того, если данные указателя уже удалены, это вызовет ту же проблему.

1 голос
/ 19 апреля 2011

Если вы запустите программу, поставьте точку останова в том месте, где вы создаете объект.Затем добавьте точку останова памяти.Это сработает, если вы перезапишите или удалите память.Ну, или измените его любым способом.

Ваш объект будет выглядеть правильно, если память не будет перезаписана, но ваша vtable может не зависеть от особенностей компилятора.

Это также может бытьпроблема размера, если вы используете наследование.Если вы используете какой-либо тип памяти или храните объекты с помощью чего-либо, кроме указателя.

...