этот указатель повреждается в трассировке стека

Я видел эту тему. Мой случай немного отличается, и я изо всех сил пытаюсь понять, как повреждается указатель "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.

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

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

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

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


person xwhatsit    schedule 30.08.2011    source источник
comment
+1, давно я видел ту же проблему с моим кодом; Я не знаю, как я это исправил; но напоминает мне старые времена. :)   -  person iammilind    schedule 30.08.2011
comment
Когда вы компилируете код, есть ли какие-либо предупреждения? Сначала исправьте их.   -  person Martin York    schedule 30.08.2011
comment
@iammilind: Это причина сделать этот вопрос любимым (нажав на звездочку), но не для того, чтобы проголосовать за него.   -  person Sebastian Mach    schedule 30.08.2011
comment
@phresnel, проголосовал за, потому что мне не терпится узнать ответ.   -  person iammilind    schedule 30.08.2011
comment
this pointer=0x4 определенно неправильно. Вы никогда не получите материал на первой странице. Что вам сейчас нужно, так это воспроизводимый тестовый пример или, по крайней мере, дамп ядра.   -  person J-16 SDiZ    schedule 30.08.2011
comment
@iammilind: Это, конечно, причина для голосования :)   -  person Sebastian Mach    schedule 30.08.2011
comment
@Martin: Никаких предупреждений, за исключением трех случаев, когда я не проверяю возвращаемое значение вызова system() (на самом деле мне все равно, успешно ли завершен процесс оболочки)   -  person xwhatsit    schedule 30.08.2011
comment
@ J-16 SDiZ: у меня есть дамп ядра, из него я выбираю свой след. Что я должен делать дальше?   -  person xwhatsit    schedule 30.08.2011
comment
Какие варианты вы используете для оптимизированной сборки? Возможно, вы захотите попробовать выборочно отключить некоторые из наиболее агрессивных оптимизаций, чтобы увидеть, сужают ли они возможности. Например, попробуйте -fno-strict-aliasing, если это включено в сборках, которые показывают проблему.   -  person Michael Burr    schedule 30.08.2011


Ответы (1)


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

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

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

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

person IronMensan    schedule 30.08.2011
comment
Другой вариант этого заключается в том, что даже если параметр передается в стек, оптимизатор может переназначить место в памяти для чего-то другого, как только это будет сделано с использованием места для параметра. Так что вполне возможно, что this pointer=0x4 в трассировке является отвлекающим маневром, особенно если параметр указателя this правильно отображается в кадрах с меньшими номерами. - person Michael Burr; 30.08.2011
comment
Спасибо за ответы. Теперь у меня отключена оптимизация, и я много работал, пытаясь снова заставить ее падать - это происходит во время перетаскивания в древовидной структуре, особенно когда сенсорный экран отправляет забавные положения, когда вы отпускаете палец, так что это не так. легко автоматизировать! Во-первых, трудно воспроизвести. Будем надеяться, что неоптимизированный дамп ядра покажет более полезные результаты. Интересно. Так что теоретически я мог бы понять, что должно быть "это", если бы я изучил ассемблер в дампе ядра и посмотрел на регистры - но это, вероятно, не поможет. - person xwhatsit; 30.08.2011