Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Отладка segv

Автор вопроса: HeretoLearnОтветов: 3

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

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

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

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

  • В какой среде вы запускаете код? Не могли бы вы приложить код, так как это облегчит вам помощь для нас, SO'ers? t0mm13b 18.12.2009

crashdebugging

Ответы

Ответ 1 · рейтинг 1 · Mark Bessey

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

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

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

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

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

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

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

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

В противном случае вы можете попробовать запустить код с отладочным пакетом malloc (доступно несколько). Даже если "ошибка" не воспроизводится, вы, вероятно, обнаружите, что таким образом неправильно манипулируете указателем.

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

Ответ 2 · рейтинг 1 · R Samuel Klatchko

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

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

Одна из моих рекомендаций - прекратить отладку, добавив трассировки, и вместо этого использовать отладчик.

Ответ 3 · t0mm13b

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы