Программная ошибка
- 1 year ago
- 0
- 0
Ошибка сегментации ( англ. 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
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++ не прослеживает такую ошибку при компоновке , что при запуске скомпилированной программы может вызвать ошибку сегментации.