[Linux] Метод анализа ошибок сегментации (сброс ядра)
[Linux] Метод анализа ошибок сегментации (сброс ядра)
😎 Об авторе: Я программист Чжоучжоу, малоизвестный программист, который любит писать. Создатель полнофункционального высококачественного поля CSDN, эксперт сообщества блогов Huawei Cloud по обмену облаками, блоггер-эксперт сообщества блогов Alibaba Cloud.
Предисловие
В системах Linux программа может столкнуться с ошибкой сегментации (Segmentation Fault) во время ее работы. Это распространенная ошибка времени выполнения, которая обычно возникает, когда программа пытается получить доступ к нераспределенной (или запрещенной) части своего пространства памяти.
При возникновении ошибки сегментации система может создать дамп ядра, который представляет собой файл, содержащий образ памяти после завершения работы программы, который можно использовать для последующей отладки и анализа проблем.
В этой статье мы рассмотрим, как анализировать сбои сегментов и использовать файлы дампа ядра для обнаружения проблемы.
1. Обзор сегмента Fault
Причины сбоя могут включать, помимо прочего:
Доступ к указателю на неверный адрес Память.
Переполнение стека, например слишком глубокий рекурсивный вызов.
Нарушение правил защиты Память.
Память за пределами (массив выходит за пределы, несовместимый тип переменной и т. д.) Получил доступ к области Память, которая вам не принадлежит.
Доступ к области данных системы,Особенно запись данных на защищенный системой адрес Память.,Наиболее распространенным является присвоение адреса указателя 0.
Многопоточная программа использует потокобезопасные функции.
Данные, читаемые и записываемые несколькими потоками, не защищены блокировками. Для глобальных данных, к которым одновременно будут обращаться несколько потоков, следует обратить внимание на защиту блокировок, иначе это легко приведет к дампу ядра.
Не стесняйтесь использовать преобразования указателей. указатель на сегмент Память,Если только не быть уверенным, что этот Память изначально был отнесен к определенной структуре или типу.,или массив этой структуры или типа,В противном случае не преобразуйте его в указатель на эту структуру или тип.,Вместо этого это Память следует скопировать в структуру или тип такого типа.,Откройте эту структуру или введите еще раз. Это связано с тем, что если начальный адрес этого абзаца не выровнен в соответствии с этой структурой или типом,затем при доступе к нему Это легко из-за автобуса ошибка и ядро dump.
Переполнение буфера также может вызвать «ошибку сегментации». Пока(1) {do}, эта проблема, скорее всего, возникнет. Чрезмерное использование sprintf или strcat может привести к заполнению определенного баффа и переполнению, поэтому лучше выполнять memset перед каждым использованием, но. Если ошибка сегментации возникает в начале, а не появляется после некоторого времени работы, вероятность переполнения буфера относительно невелика.
Ошибка сегментации означает, что доступная память превышает объем памяти, предоставленный системой программе. Обычно это значение сохраняется в gd tr. Это 48-битный регистр, 32 бита которого сохраняют указанную в нем таблицу gdt. последние 13 бит хранят нижний индекс, соответствующий GDT, а последние 3 бита включают информацию о том, находится ли программа в памяти, и уровень выполнения программы в ЦП, указывая на GDT представляет собой таблицу с 64 битами в качестве единицы измерения. В этой таблице хранятся сегмент кода и сегмент данных программы.
Как только программа получает доступ за пределы границ, ЦП сгенерирует соответствующую защиту, поэтому возникает ошибка сегментации. Согласно приведенному выше объяснению, ошибка сегментации должна заключаться в доступе к недоступной памяти. Эта область памяти либо не существует, либо на нее влияет. Для защиты системы могут отсутствовать или быть повреждены файлы. # 2. Файл дампа ядра
Когда программа завершается из-за ошибки сегмента, если конфигурация системы позволяет создавать дампы ядра, будет создан файл ядра (или аналогичный шаблон именования), содержащий образ памяти программы на момент ее завершения.
Конфигурация дампа ядра
Фактически система запишет всю информацию о ядре в файл в момент сбоя программы (ls этот файл не увидит)
Убедитесь, что конфигурация /proc/sys/kernel/core_pattern позволяет создавать файлы дампа ядра.
Установите ulimit, чтобы разрешить создание основных файлов:
Язык кода:javascript
копировать
Добавьте следующую строку в /etc/profile,Это позволит создать файл дампа памяти.
ulimit-c безлимитный
Обязательно добавьте параметр -g при компиляции, иначе при отображении ошибки в конце будет отображаться только неправильный адрес, а конкретная информация об ошибке отображаться не будет.
/proc/sys/kernel/core_uses_pid может контролировать, добавляется ли pid в качестве расширения к имени файла ядра. Если содержимое файла равно 1, это означает добавление pid в качестве расширения, а сгенерированный формат файла ядра — core.xxxx. Если он равен 0, это означает, что сгенерированный файл ядра также называется core.
Этот файл можно изменить с помощью следующей команды:
Язык кода:javascript
копировать
echo "1" > /proc/sys/kernel/core_uses_pid
Как правило, основной путь и исполняемая программа совпадают.
Кроме того, вы также можете установить шаблон имени файла ядра в /proc/sys/kernel/core-pattern.
Подтвердите существование файла дампа ядра.
При сбое программы проверьте, создается ли файл дампа ядра в текущем каталоге или в местоположении, указанном core_pattern.
Используйте отладчик для анализа дампов ядра
Используйте GDB (GNU Отладчик) или другой отладчик загружает файл дампа ядра и соответствующий исполняемый файл программы и анализирует стек вызовов и состояние переменной на момент сбоя.
Язык кода:javascript
копировать
gdb /path/to/program /path/to/coredump
Проверьте стек вызовов
В gdb используйте команду backtrace (или сокращенно bt) для просмотра стека вызовов во время сбоя.
Проверьте переменную и статус регистрации
Используйте команду print (или сокращенно p), чтобы проверить значение определенной переменной и информационных регистров, чтобы просмотреть состояние регистра.
Проверьте исходный код построчно
На основе информации о стеке вызовов найдите конкретный номер строки в исходном коде и проверьте соответствующую логику кода.
Рассмотрим шаблон доступа Память
Проанализируйте шаблон доступа Память программы и проверьте, нет ли доступа за пределами границ, неправильных операций с указателем и т. д.
Проверка среды выполнения
Убедитесь, что конфигурация и среда выполнения программы могут привести к сбою сегмента.
Параметры компилятора и компоновщика
Скомпилируйте программу с опцией -g, чтобы обеспечить целостность отладочной информации. Используйте такие инструменты, как valgrind, чтобы проверить наличие ошибок Память.
На что следует обратить внимание
Своевременные обновления системы и инструментов: убедитесь, что вы используете последнюю версию системы.、Компиляторы и инструменты отладки.
Подробное протоколирование ошибок: регистрируется полная трассировка стека и другая соответствующая информация при возникновении сбоя сегмента.
Многофакторный анализ: анализируйте проблемы с разных точек зрения кода, данных и операционной среды.