"this" указатель получает повреждение в трассировке стека

Я видел this поток. Мое дело немного другое, и я изо всех сил пытаюсь понять, как выглядит "this" указатель.

Я использую структуру Qt 4.6.2, используя их QTreeView с моей собственной моделью. Я получаю обратную трассировку (86 кадров в длину, с большой рекурсией, поэтому я не вставлял все это в нее pastebin включает только код.

Он, наконец, segfaults на каком-то ассемблере в QBasicAtomicInt:: deref, но очевидно, что он умер дальше вниз, о чем свидетельствуют эти три кадра:

#15 0x01420fd3 in QFrame::event (this=0x942bba0, e=0xbf8eb624) at widgets/qframe.cpp:557
#16 0x014bb382 in QAbstractScrollArea::viewportEvent (this=0x4, e=0x93f9240) at widgets/qabstractscrollarea.cpp:1036
#17 0x0156fbd7 in QAbstractItemView::viewportEvent (this=0x942bba0, event=0xbf8eb624) at itemviews/qabstractitemview.cpp:1610

В кадре 17 this есть 0x942bb0. В кадре 16 this должен быть таким же, как в кадре 17, он вызывает реализацию своего предшественника того же метода. Однако this становится 0x4.

Интересно, что в кадре 15 (опять же, кадр 16 назвал реализацию своего предка той же функцией), указатель 'this' будет восстановлен до 0x942bba0.

Если вы посмотрите на пастик полной обратной линии, вы можете увидеть некоторые "оптимизированные значения". У меня было приложение, скомпилированное с оптимизацией; Теперь у меня есть gcc для -g3 -O0, поэтому, когда это произойдет в следующий раз, у меня может получиться нечто большее. Но, конечно, теперь я не могу заставить его потерпеть крах - это довольно сложная ошибка, которая может произойти (но очень важно исправить, тем не менее), поэтому я не думаю, что это слишком подозрительно.

Учитывая оптимизацию, заключается в том, что this pointer=0x4 необычный или определенно неправильный? Что странно, так это то, что в любом из этих кадров viewportEvent нет реального кода - они просто переключаются на тип события, он попадает через оператор switch и возвращает реализацию своего предка.

Valgrind, похоже, не вызывает каких-либо проблем, хотя я еще не сделал его крахом в Valgrind.

Кто-нибудь видел это поведение раньше? Что может быть причиной этого?

Ответ 1

Я видел это раньше, когда отлаживал оптимизированные сборки, и он никогда не был признаком того, что для меня реальная ошибка.

Легче сначала подумать о локальной переменной. В не оптимизированной сборке все имеет свое обозначенное место в памяти и должно храниться после каждой строки кода. Это значит, что отладчик может его найти. В оптимизированной сборке значения могут записываться в регистры без записи в память. Это большая часть улучшенной производительности оптимизированной сборки. Отладчик не понимает этого и всегда будет смотреть на память, поэтому вы часто увидите неправильное значение.

То же самое может случиться с параметрами. Если оптимизатор решает передать параметр в регистр, отладчик все еще будет смотреть на стеке. Более конкретно, в месте, где параметр будет соответствовать правилам вызывающего соглашения.

Тот факт, что следующий фрейм стека имеет правильно восстановленное значение, указывает, что сгенерированные инструкции правильно обрабатывают этот параметр, но отладчик просто не знает, где его искать.