it-swarm.com.ru

Что такое ошибка сегментации?

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

509
Rajendra Uppal

Ошибка сегментации - это особая ошибка, возникающая из-за доступа к памяти, которая "не принадлежит вам". Это вспомогательный механизм, который удерживает вас от повреждения памяти и внесения трудно исправляемых ошибок памяти. Всякий раз, когда вы получаете 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.

596
zoul

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

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

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

102
konrad.kruczynski

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

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

32
Ignacio Vazquez-Abrams

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

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

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

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

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

15
Orhan Cinar

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

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

Правка:

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

11
Alejo Bernardin

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

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here
7
Sohail xIN3N

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

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

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

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

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

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

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

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

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

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

5
Roy

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

3
FilipeCanatto

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

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

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

1
Viktor Nonov

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

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

Здесь я [1000] не существует, поэтому происходит ошибка.

Причины ошибки сегментации:

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers – this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside process’s address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).
0
Mohit Rohilla

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

Первая проблема с вашими аргументами главного. Основная функция должна быть int main (int argc, char * argv []), и вы должны проверить, что argc равен по крайней мере 2, прежде чем получить доступ к argv [1].

Кроме того, поскольку вы передаете float в printf (который, кстати, преобразуется в double при переходе в printf), вы должны использовать спецификатор формата% f. Спецификатор формата% s предназначен для строк (символьные массивы, оканчивающиеся на\0).

0
PHP Worm...