Что такое ошибка сегментации? - PullRequest
511 голосов
/ 27 февраля 2010

Что такое ошибка сегментации? Отличается ли это в C и C ++? Как связаны ошибки сегментации и висячие указатели?

Ответы [ 12 ]

599 голосов
/ 27 февраля 2010

Ошибка сегментации - это особая ошибка, возникающая из-за доступа к памяти, которая «не принадлежит вам». Это вспомогательный механизм, который удерживает вас от повреждения памяти и внесения трудных для отладки ошибок памяти. Всякий раз, когда вы получаете segfault, вы знаете, что делаете что-то не так с памятью - обращаетесь к переменной, которая уже была освобождена, записываете в доступную только для чтения часть памяти и т. Д. Ошибка сегментации практически одинакова в большинстве языков, которые позволяют вам связываться с В управлении памятью нет принципиальной разницы между ошибками в C и C ++.

Есть много способов получить segfault, по крайней мере, на языках более низкого уровня, таких как C (++). Распространенный способ получить segfault - разыменовать нулевой указатель:

int *p = NULL;
*p = 1;

Другая ошибка возникает, когда вы пытаетесь записать часть памяти, помеченную как доступную только для чтения:

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

Свисающий указатель указывает на то, что больше не существует, как здесь:

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

Указатель p болтается, потому что он указывает на символьную переменную c, которая перестала существовать после окончания блока. И когда вы попытаетесь разыменовать висячий указатель (например, *p='A'), вы, вероятно, получите segfault.

104 голосов
/ 04 июля 2011

Стоит отметить, что ошибка сегментации не вызвана прямым доступом к другой памяти процесса (это то, что я иногда слышу), поскольку это просто невозможно. С виртуальной памятью каждый процесс имеет свое собственное виртуальное адресное пространство, и нет никакого способа получить доступ к другому, используя любое значение указателя. Исключением из этого могут быть разделяемые библиотеки, которые представляют собой одно и то же физическое адресное пространство, сопоставленное (возможно) разным виртуальным адресам и памяти ядра, которая даже отображается одинаково в каждом процессе (я думаю, что во избежание сброса TLB на системный вызов) И такие вещи, как shmat;) - это то, что я считаю «косвенным» доступом. Однако можно проверить, что они обычно расположены далеко от кода процесса, и мы, как правило, можем получить к ним доступ (вот почему они есть, но, тем не менее, неправильный доступ к ним вызовет ошибку сегментации).

Тем не менее, ошибка сегментации может возникнуть в случае неправильного доступа к нашей собственной (процессной) памяти (например, при попытке записи в недоступное для записи пространство). Но наиболее распространенной причиной этого является доступ к той части виртуального адресного пространства, которая вообще не сопоставлена ​​ с физической.

И все это в отношении систем виртуальной памяти.

32 голосов
/ 27 февраля 2010

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

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

27 голосов
/ 27 февраля 2010

Если честно, как упоминали другие авторы, в Википедии есть очень хорошая статья на эту тему , так что посмотрите. Этот тип ошибки очень распространен и часто называется другими вещами, такими как нарушение прав доступа или Ошибка общей защиты.

Они не отличаются в C, C ++ или любом другом языке, который позволяет указатели. Такие ошибки обычно вызываются указателями, которые

  1. Используется перед правильной инициализацией
  2. Используется после того, как память, на которую они указывают, была восстановлена ​​или удалена.
  3. Используется в индексированном массиве, где индекс находится за пределами границ массива. Обычно это происходит только тогда, когда вы выполняете математические операции с указателями на традиционных массивах или c-строках, а не на коллекциях на основе STL / Boost (в C ++.)
15 голосов
/ 27 февраля 2010

Согласно википедии:

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

11 голосов
/ 24 июня 2014

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

Решение в этом случае изменить оперативную память.

редактирование:

Здесь есть ссылка: Ошибка сегментации по аппаратным средствам

7 голосов
/ 11 декабря 2013

Ошибка сегментации возникает, когда процесс (запущенный экземпляр программы) пытается получить доступ к адресу памяти только для чтения или диапазону памяти, который используется другим процессом, или получить доступ к несуществующему (недействительно) адрес памяти. Проблема с висячей ссылкой (указателем) означает, что попытка получить доступ к объекту или переменной, содержимое которой уже было удалено из памяти, например:

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here
5 голосов
/ 14 октября 2014

Википедия Segmentation_fault содержит очень хорошее описание, просто указывая причины и причины. Загляните в вики для подробного описания.

В вычислительной технике ошибка сегментации (часто сокращенная до segfault) или нарушение доступа - это ошибка, вызванная оборудованием с защитой памяти, уведомляющее операционную систему (ОС) о нарушении доступа к памяти.

Ниже приведены некоторые типичные причины ошибки сегментации:

  • Разыменование указателей NULL - это специально для оборудования управления памятью
  • Попытка доступа к несуществующему адресу памяти (вне адресного пространства процесса)
  • Попытка доступа к памяти, на которую у программы нет прав (например, структуры ядра в контексте процесса)
  • Попытка записи в постоянную память (например, сегмент кода)

Это, в свою очередь, часто вызвано ошибками программирования, которые приводят к неправильному доступу к памяти:

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

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

  • Переполнение буфера.

  • Переполнение стека.

  • Попытка выполнить программу, которая неправильно компилируется. (Некоторые компиляторы выводят исполняемый файл, несмотря на наличие ошибок времени компиляции.)

3 голосов
/ 19 июля 2017

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

1 голос
/ 13 октября 2018

В ответах есть несколько хороших объяснений «ошибки сегментации», но поскольку в случае ошибки сегментации часто возникает дамп содержимого памяти, я хотел бы поделиться тем, где взаимосвязь между частью «сбрасывается ядро» в сегментации ошибка (ядро сброшено) и память поступает из:

Примерно с 1955 по 1975 годы - до появления полупроводниковой памяти - доминирующая технология в компьютерной памяти использовала крошечные магнитные пончики, нанизанные на медные провода. Пончики были известны как «ферритовые сердечники», а основная память, таким образом, называлась «памятью сердечника» или «ядром».

Взято из здесь .

...