Linux SIGSEGVВысокая

Исправление segmentation fault (SIGSEGV) в программах на C под Linux

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

Обновлено 5 августа 2026 г.
5-10 мин
Средняя
FixPedia Team
Применимо к:GCC 11+, Clang 14+, Ubuntu 22.04, Debian 12, Fedora 38

Что означает ошибка SIGSEGV

Segfault (сигнал SIGSEGV) — это авария, при которой программа на C пытается прочитать или записать память, которая не принадлежит ей. Операционная система прерывает процесс, чтобы предотвратить повреждение данных или сбой системы. Типичные причины:

  • Использование NULL-указателя или указателя, который никогда не был инициализирован.
  • Выход за границы массива или буфера.
  • Попытка освободить память дважды или обратиться к уже освобождённой памяти.
  • Нарушение правил выравнивания при работе с указателями.

Сообщение об ошибке обычно выглядит так:

Segmentation fault (core dumped)

или, если используется GDB:

Примечание: программа только что вызвала прерывание SIGSEGV.
(gdb) bt
#0  0x0000555555555a5f в 0x...

Причины возникновения

  1. Нулевой указатель – чтение/запись по адресу NULL.
  2. Выход за границы массива – доступ к элементу за пределами выделенного массива.
  3. Ошибки с указателями на функции – вызов NULL- или повреждённого указателя на функцию.
  4. Освобождение памяти дважды – повторный вызов free.
  5. Использование памяти после освобождения – чтение данных после free.
  6. Нарушение выравнивания – доступ к типу, требующему определённого выравнивания, по неправильному адресу.

Способы решения

Способ 1: Отладка с помощью GDB

GDB позволяет остановить процесс непосредственно в момент сбоя и получить трассировку стека.

gdb ./a.out          # запустить GDB
run                  # выполнить программу
# когда программа упадёт:
backtrace            # показать стек вызовов

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

Способ 2: Использовать AddressSanitizer (ASan)

Добавьте инструмент обнаружения ошибок при компиляции:

gcc -fsanitize=address -g -O0 main.c -o prog
./prog

ASan выведет отчёт, например:

==32098==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61000040 at pc 0x...
READ of size 4 at 0x61000040 thread T0
...

Теперь вы точно знаете, где произошёл выход за границы буфера.

Способ 3: Запустить программу под Valgrind

Valgrind симулирует выполнение и отслеживает доступ к памяти:

valgrind ./prog

Пример вывода:

==32100== Invalid read of size 1, at 0x61000040 ...
==32100==    by 0x4008d6 в my_function ...

Valgrind также показывает номер строки и имя файла.

Способ 4: Исправить выявлённую ошибку

После получения отчёта отладчика:

  • Проверьте указатели на NULL, прежде чем использовать их.
  • Убедитесь, что индексы массивов находятся в пределах [0, size-1].
  • Используйте безопасные функции (strncpy, fgets, snprintf).
  • Следите за выделением и освобождением памяти: выделяйте один раз и освобождайте один раз.

Пример исправления:

char *ptr = NULL;
ptr = malloc(len);
if (!ptr) {
    perror("malloc");
    return 1;
}
strncpy(ptr, src, len - 1);
ptr[len - 1] = '\0';
free(ptr);

Способ 5: Статический анализ кода

Статические анализаторы, такие как clang-check или cppcheck, могут обнаружить ошибки до компиляции:

clang-check main.c -- -Wall -Wextra
cppcheck --enable=warning main.c

Они часто предупреждают о потенциальных проблемах с указателями, использовании памяти и выходе за границы массива.

Профилактика

  • Проверяйте указатели перед использованием: if (!ptr) handle_error();.
  • Используйте безопасные функции из стандартной библиотеки, которые ограничивают размер копирования.
  • Включайте инструменты обнаружения ошибок (-fsanitize=address, -fsanitize=undefined) в CI-пайплайнах.
  • Регулярно запускайте Valgrind/AddressSanitizer при локальной разработке.
  • Проводите статический анализ перед коммитом (например, clang-tidy).
  • Следите за версиями компилятора: новые версии GCC/Clang улучшают диагностику.

Регулярное тестирование и внимательность к предупреждениям от компилятора помогут избежать segfault в продакшн-коде.

Часто задаваемые вопросы

Что означает segmentation fault при запуске программы на C?
Как быстро воспроизвести segfault для отладки?
Можно ли обнаружить segfault без ручного отладчика?
Как предотвратить segfault в продакшн-коде?

Полезное

Запустить программу с GDB
Использовать AddressSanitizer при компиляции
Запустить программу под Valgrind
Исправить обнаруженную ошибку
Пересобрать и протестировать

Эта статья помогла вам решить проблему?