Что такое ошибка сегментации? Различен ли он в C и C ++? Как связаны ошибки сегментации и висячие указатели?
NullPointerException
.
Что такое ошибка сегментации? Различен ли он в C и C ++? Как связаны ошибки сегментации и висячие указатели?
NullPointerException
.
Ответы:
Ошибка сегментации - это особая ошибка, вызванная доступом к памяти, которая «не принадлежит вам». Это вспомогательный механизм, который не дает вам повредить память и вводить трудно исправляемые ошибки памяти. Всякий раз, когда вы получаете 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.
c
это локально, это означает, что он был помещен в стек после {
и выскочил из него после }
. висячий указатель - это просто ссылка на смещение, которое теперь находится вне стека. вот почему изменение его в простой программе никогда не вызовет никакого сбоя. с другой стороны, это может привести к segfault в более сложном случае, когда другие вызовы функций могут привести к росту стека и содержанию данных, на которые указывает свисающий указатель. запись в эти данные (локальные переменные) приведет к неопределенному поведению (segfault & Co)
SIGSEGV
, поэтому я не ожидаю, что такой сигнал искажается стеком.
Стоит отметить, что ошибка сегментации не вызвана прямым доступом к другой памяти процесса (это то, что я иногда слышу), поскольку это просто невозможно. С виртуальной памятью каждый процесс имеет свое собственное виртуальное адресное пространство, и нет никакого способа получить доступ к другому, используя любое значение указателя. Исключением из этого могут быть общие библиотеки, которые представляют собой одно и то же физическое адресное пространство, сопоставленное (возможно) разным виртуальным адресам и памяти ядра, которая даже отображается одинаково в каждом процессе (я думаю, что во избежание сброса TLB на syscall). И такие вещи, как shmat;) - это то, что я считаю «косвенным» доступом. Однако можно проверить, что они обычно расположены далеко от кода процесса, и мы обычно можем получить к ним доступ (вот почему они есть,
Тем не менее, ошибка сегментации может возникать в случае неправильного доступа к нашей собственной (процессной) памяти (например, при попытке записи в недоступное для записи пространство). Но наиболее распространенной причиной этого является доступ к той части виртуального адресного пространства, которая вообще не сопоставлена с физической.
И все это в отношении систем виртуальной памяти.
Ошибка сегментации вызвана запросом на страницу, которую процесс не указал в своей таблице дескрипторов, или неправильным запросом на страницу, которую он перечислил (например, запрос на запись на странице только для чтения).
Висячий указатель - это указатель, который может указывать или не указывать на допустимую страницу, но указывает на «неожиданный» сегмент памяти.
Честно говоря, как упоминали другие авторы, в Википедии есть очень хорошая статья на эту тему, так что загляните туда. Этот тип ошибки очень распространен и часто называется другими вещами, такими как нарушение прав доступа или общая ошибка защиты.
Они ничем не отличаются в C, C ++ или любом другом языке, который позволяет указатели. Такие ошибки обычно вызываются указателями, которые
Согласно википедии:
Ошибка сегментации возникает, когда программа пытается получить доступ к области памяти, к которой у нее нет доступа, или пытается получить доступ к области памяти недопустимым способом (например, при попытке записи в область только для чтения или перезаписать часть операционной системы).
Ошибка сегментации также вызвана аппаратными сбоями, в данном случае памятью ОЗУ. Это менее распространенная причина, но если вы не нашли ошибку в своем коде, возможно, вам поможет memtest.
Решение в этом случае изменить оперативную память.
редактировать:
Здесь есть ссылка: Ошибка сегментации по аппаратному обеспечению
Ошибка сегментации возникает, когда процесс (запущенный экземпляр программы) пытается получить доступ к адресу памяти только для чтения или диапазону памяти, который используется другим процессом, или получить доступ к несуществующему (недействительному) адресу памяти. Проблема с висячей ссылкой (указателем) означает, что при попытке доступа к объекту или переменной, содержимое которой уже удалено из памяти, например:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
Страница Wikipedia Segmentation_fault содержит очень хорошее описание, просто указывая причины и причины. Загляните в вики для подробного описания.
В вычислительной технике ошибка сегментации (часто сокращенная до segfault) или нарушение доступа - это ошибка, возникающая от оборудования с защитой памяти, уведомляющего операционную систему (ОС) о нарушении доступа к памяти.
Ниже приведены некоторые типичные причины ошибки сегментации:
Это, в свою очередь, часто вызвано ошибками программирования, которые приводят к неправильному доступу к памяти:
Разыменование или присвоение неинициализированному указателю (дикий указатель, который указывает на случайный адрес памяти)
Разыменование или присвоение освобожденному указателю (висячий указатель, который указывает на память, которая была освобождена / освобождена / удалена)
Переполнение буфера.
Переполнение стека.
Попытка выполнить программу, которая не компилируется правильно. (Некоторые компиляторы выводят исполняемый файл, несмотря на наличие ошибок во время компиляции.)
Проще говоря: ошибка сегментации - это операционная система, посылающая программе сигнал о том, что она обнаружила несанкционированный доступ к памяти и преждевременно завершает работу программы, чтобы предотвратить повреждение памяти.
«Ошибка сегментации» означает, что вы пытались получить доступ к памяти, к которой у вас нет доступа.
Первая проблема с вашими аргументами главного. Основная функция должна быть int main(int argc, char *argv[])
, и вы должны проверить, что argc по крайней мере 2, прежде чем получить доступ к argv [1].
Кроме того, поскольку вы передаете float в printf (который, кстати, преобразуется в double при переходе в printf), вы должны использовать спецификатор формата% f. Спецификатор формата% s предназначен для строк (символьные массивы, оканчивающиеся на \ 0).
Ошибка сегментации или нарушение доступа возникает, когда программа пытается получить доступ к ячейке памяти, которая не существует, или пытается получить доступ к ячейке памяти способом, который не разрешен.
/* "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).
В ответах есть несколько хороших объяснений «ошибки сегментации», но поскольку в случае ошибки сегментации часто возникает дамп содержимого памяти, я хотел бы поделиться тем, где взаимосвязь между частью «сбрасывать ядро» в ошибке сегментации (ядро сбрасывается) и память приходит от:
Примерно с 1955 по 1975 годы - до появления полупроводниковой памяти - доминирующая технология в компьютерной памяти использовала крошечные магнитные пончики, нанизанные на медные провода. Пончики были известны как «ферритовые сердечники», а основная память, таким образом, известна как «внутренняя память» или «ядро».
Взято отсюда .
Существует достаточно определений ошибок сегментации, я хотел бы привести несколько примеров, с которыми я сталкивался во время программирования, что может показаться глупой ошибкой, но потраченной впустую много времени.
Вы можете получить ошибку сегментации в нижнем регистре, в то время как несоответствие типа аргумента в printf
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
вывод : Segmentation Fault (SIGSEGV)
когда вы забыли выделить память для указателя, но пытаетесь его использовать.
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
вывод : Segmentation Fault (SIGSEGV)
Простой смысл в Segmentation fault
том, что вы пытаетесь получить доступ к памяти, которая не принадлежит вам. Segmentation fault
происходит, когда мы пытаемся читать и / или записывать задачи в области памяти, доступной только для чтения, или пытаемся освободить память. Другими словами, мы можем объяснить это как своего рода повреждение памяти.
Ниже я упоминаю распространенные ошибки программистов, которые приводят к Segmentation fault
.
scanf()
неправильно (забыл поставить &
).int num;
scanf("%d", num);// must use &num instead of num
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
printf()
и scanf()
'