Отладка сегва - PullRequest
       8

Отладка сегва

1 голос
/ 18 декабря 2009

Я уверен, что многие из вас испытали это. Иногда при отладке сбоя вы добавляете строку трассировки и альта сбой исчезает. Как правило, это указывает на повреждение памяти, и вы ищете переполнения буфера и т. Д. Вокруг кода. Чтобы быть более конкретным, то же самое происходит даже для однопоточных приложений.

Как, хотя линия трассировки предотвращает сбой?

Строка трассировки - это кусок кода, так что следует перейти к сегменту кода, так как он только для чтения, верно?

Это не должно повлиять на локальный стек выполнения? Как это влияет на смещение указателей, чтобы заставить какой-то другой фрагмент памяти перезаписываться, что само по себе не проявляется (все еще плохо).

Ответы [ 3 ]

1 голос
/ 18 декабря 2009

Во-первых, трассировка может влиять не только на сегмент кода, но и на сегмент данных, если в трассировке содержится какая-то строка. Это может полностью изменить расположение вашей памяти.

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

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

1 голос
/ 18 декабря 2009

Несколько человек уже упоминали изменения времени. Даже если ваш код однопоточный, вы можете вызывать API, который либо запускает потоки от вашего имени, либо реализует какую-то другую форму асинхронного взаимодействия.

Что касается этого утверждения:

Трассировка - это кусок кода, поэтому следует перейти к сегменту кода

Это зависит от того, что на самом деле ваш код трассировки делает . Даже что-то простое, как:

write(0, "Hello, World!\n", 14);

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

Более сложный вызов трассировки, который, например, вызывает fwrite или printf, почти наверняка приведет к выделению некоторой памяти для временных буферов и т. Д.

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

Если это не удастся, вы можете попробовать запустить код с отладочным пакетом malloc (доступно несколько). Даже если «ошибка» не воспроизводится, вы, скорее всего, обнаружите некоторые неправильные манипуляции с указателем.

Последнее предложение: перекомпилируйте ваш код со всеми предупреждениями, включенными в компиляторе, и серьезно рассмотрите все сгенерированные предупреждения. Обратите внимание, что при gcc -Wall не включает все предупреждения.

0 голосов
/ 18 декабря 2009

Пожалуйста, смотрите здесь для моего ответа на другой вопрос SO. Я не уверен на 100%, в какой среде вы работаете, но я думаю, что это один из вариантов Unix ... Ссылка, которую я дал, демонстрирует простой трюк, чтобы перехватить обработчик SIGSEGV, подключив обработчик signal и в любое время во время выполнения кода обработчик перехватывается и сбрасывает трассировку стека в файл для чтения.

Надеюсь, это поможет вам отследить проблему, С наилучшими пожеланиями, Том.

...