Interested Article - Ошибка сегментации

Ошибка сегментации ( англ. Segmentation fault , сокр. segfault , жарг. сегфолт ) — ошибка программного обеспечения , возникающая при попытке обращения к недоступным для записи участкам памяти либо при попытке изменить память запрещённым способом. В системах на основе процессоров Motorola 6800 эти ошибки, как правило, известны как ошибки адреса или шины .

В UNIX-подобных операционных системах процесс, обращающийся к недействительным участкам памяти, получает сигнал SIGSEGV . В Microsoft Windows процесс, получающий доступ к недействительным участкам памяти, создаёт исключение STATUS_ACCESS_VIOLATION (определение для кода 0xC0000005 ) и, как правило, предлагает запустить отладчик приложения и показывает пользователю окно с предложением отправить отчёт об ошибке в Microsoft .

Пример

Вот пример кода ANSI C , который приводит к ошибке сегментации из-за присутствия квалификатора типа const :

const char * s = "hello world";
* (char *) s = 'H';

Когда программа , содержащая этот код, скомпилирована , строка "hello world" размещена в секции программы с бинарной пометкой «только для чтения». При запуске операционная система помещает её с другими строками и константами в сегмент памяти, предназначенный только для чтения. После запуска переменная s указывает на адрес начала строки , а попытка присвоить значение символьной константы 'H' через переменную в памяти приводит к ошибке сегментации.

Компиляция и запуск таких программ на OpenBSD 4.0 вызывает следующую ошибку выполнения:

$ gcc segfault.c -g -o segfault
$ ./segfault
Segmentation fault

Вывод отладчика gdb :

Program received signal SIGSEGV, Segmentation fault.
0x1c0005c2 in main () at segfault.c:6
6 *s = 'H';

В отличие от этого, GCC 4.1.1 на GNU/Linux возвращает ошибку ещё во время компиляции :

$ gcc segfault.c -g -o segfault
segfault.c: In function 'main':
segfault.c:4: error: assignment of read-only location

Условия, при которых происходят нарушения сегментации, и способы их проявления зависят от операционной системы .

Этот пример кода создаёт нулевой указатель и пытается присвоить значение по несуществующему адресу. Это вызывает ошибки сегментации во время выполнения программы на многих системах .

int * ptr = (int *) 0;
*ptr = 1;

Ещё один способ вызвать ошибку сегментации заключается в том, чтобы вызвать функцию main() рекурсивно , что приведёт к переполнению стека :

int main()
{
    main();
}

Обычно ошибка сегментации происходит потому, что:

  • указатель нулевой,
  • указатель указывает на произвольный участок памяти (возможно потому, что не был инициализирован ),
  • указатель указывает на удалённый участок памяти.

Например,

char * p1 = NULL; /* инициализирован как нулевой; это допускается, но на многих системах он не может быть разыменован */
char * p2; /* вообще не инициализирован (указывает на произвольный адрес в памяти) */
char * p3 = (char *) malloc(20); /* хорошо, участок памяти выделен */
free(p3); /* но теперь его больше нет */

Теперь разыменование любого из этих указателей может вызвать ошибку сегментации.

Или при использовании массивов , если случайно указать в качестве размера массива неинициализированную переменную :

int main()
{
    const int nmax = 10;
    int i, n, a[n];
}

Компилятор G++ не прослеживает такую ошибку при компоновке , что при запуске скомпилированной программы может вызвать ошибку сегментации.

См. также

Примечания

  1. (англ.) . Дата обращения: 27 января 2022. 27 января 2022 года.

Ссылки

Источник —

Same as Ошибка сегментации