Czym jest błąd segmentacji?

Co to jest wada segmentacji? Czy w C i C++jest inaczej? Jak powiązane są błędy segmentacji i zwisające wskaźniki?

Author: Jonathan Leffler, 2010-02-27

15 answers

Błąd segmentacji jest specyficznym rodzajem błędu spowodowanego dostępem do pamięci, która "nie należy do ciebie."Jest to mechanizm pomocniczy, który zapobiega uszkodzeniom pamięci i wprowadzaniu trudnych do debugowania błędów pamięci. Za każdym razem, gdy otrzymujesz segfault, wiesz, że robisz coś złego z pamięcią – dostęp do zmiennej, która została już uwolniona, zapis do tylko do odczytu części pamięci itp. Błąd segmentacji jest zasadniczo taki sam w większości języków, które pozwalają na bałagan z pamięcią zarządzanie, nie ma zasadniczej różnicy między segfaults w C i C++.

Istnieje wiele sposobów na uzyskanie segfault, przynajmniej w językach niższego poziomu, takich jak C (++). Aby uzyskać segfault, należy zdereferować wskaźnik null:
int *p = NULL;
*p = 1;

Inny segfault dzieje się, gdy próbujesz zapisać do części pamięci, która została oznaczona jako Tylko do odczytu:

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

Wiszący wskaźnik wskazuje na rzecz, która już nie istnieje, jak tutaj:

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

Wskaźnik p zwisa ponieważ wskazuje na zmienną znakową c, która przestała istnieć po zakończeniu bloku. A gdy spróbujesz dereferencji zwisającego wskaźnika (np. *p='A'), prawdopodobnie dostaniesz segfault.

 742
Author: zoul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-23 12:54:37

Warto zauważyć, że błąd segmentacji nie jest spowodowany bezpośrednim dostępem do innej pamięci procesowej (to jest to, co czasami słyszę), ponieważ jest to po prostu niemożliwe. Z pamięcią wirtualną każdy proces ma swoją własną wirtualną przestrzeń adresową i nie ma możliwości uzyskania dostępu do innej przy użyciu dowolnej wartości wskaźnika. Wyjątkiem mogą być biblioteki współdzielone, które są tą samą fizyczną przestrzenią adresową mapowaną na (ewentualnie) różne adresy wirtualne i pamięć jądra, która jest nawet mapowana w tak samo w każdym procesie (aby uniknąć spłukiwania TLB na syscall, myślę). I takie rzeczy jak shmat ;) - to właśnie zaliczam do "pośredniego" dostępu. Można jednak sprawdzić, czy zazwyczaj znajdują się one daleko od kodu procesowego i zazwyczaj mamy do nich dostęp (dlatego właśnie tam są, jednak dostęp do nich w niewłaściwy sposób spowoduje błąd segmentacji).

Mimo to, błąd segmentacji może wystąpić w przypadku nieprawidłowego dostępu do naszej pamięci (procesowej) (na przykład próba zapisu do przestrzeni nie nadającej się do zapisu). Ale najczęstszym powodem tego jest dostęp do części wirtualnej przestrzeni adresowej, która nie jest w ogóle mapowana na fizyczną.

I to wszystko w odniesieniu do systemów pamięci wirtualnej.

 116
Author: konrad.kruczynski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-10 21:58:03

Błąd segmentacji jest spowodowany żądaniem strony, której proces nie ma w swojej tabeli deskryptorów, lub błędnym żądaniem strony, którą ma w swojej tabeli (np. żądanie zapisu na stronie Tylko do odczytu).

Zwisający wskaźnik jest wskaźnikiem, który może, ale nie musi, wskazywać na poprawną stronę, ale wskazuje na "nieoczekiwany" segment pamięci.

 40
Author: Ignacio Vazquez-Abrams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-27 09:27:03

Szczerze mówiąc, jak wspominały inne plakaty, Wikipedia ma bardzo dobry artykuł na ten temat więc zajrzyj tam. ten typ błędu jest bardzo powszechny i często nazywany innymi rzeczami, takimi jak naruszenie dostępu lub ogólny błąd ochrony.

Nie różnią się one w C, C++ ani w żadnym innym języku, który pozwala na wskaźniki. Tego rodzaju błędy są zwykle spowodowane przez wskaźniki, które są

  1. używane przed prawidłowym zainicjowaniem
  2. używane po pamięci wskazują na została ponownie przydzielona lub usunięta.
  3. używany w zindeksowanej tablicy, gdzie indeks znajduje się poza granicami tablicy. Zwykle jest to tylko wtedy, gdy wykonujesz matematykę wskaźnikową na tradycyjnych tablicach lub ciągach c, a nie na kolekcjach opartych na STL / Boost (w C++.)
 34
Author: Component 10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-27 20:35:23

Według Wikipedii :

Błąd segmentacji występuje, gdy program próbuje uzyskać dostęp do pamięci miejsce, w którym nie wolno dostęp lub próby uzyskania dostępu do pamięci lokalizacja w sposób niedozwolony (np. próba napisania do lokalizacja tylko do odczytu, lub do nadpisania część systemu operacyjnego).

 18
Author: Orhan Cinar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-16 23:40:28

Błąd segmentacji jest również spowodowany awariami sprzętu, w tym przypadku pamięci RAM. Jest to mniej powszechna przyczyna, ale jeśli nie znajdziesz błędu w kodzie, może pomoże Ci memtest.

Rozwiązanie w tym przypadku zmień PAMIĘĆ RAM.

Edit:

Tutaj jest odniesienie: segmentacja błąd przez sprzęt

 15
Author: Alejo Bernardin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-27 19:37:02

Strona Wikipedii Segmentation_fault ma bardzo ładny opis na jej temat, wskazując tylko przyczyny i powody. Zajrzyj do wiki, aby uzyskać szczegółowy opis.

[[0]} w komputerach błąd segmentacji (często skracany do segfault) lub naruszenie dostępu to błąd powodowany przez sprzęt z ochroną pamięci, powiadamiający system operacyjny (OS) o naruszeniu dostępu do pamięci.

Oto kilka typowych przyczyn segmentacji błąd:

  • Dereferencing NULL pointers – jest to specjalne-obudowane przez sprzęt do zarządzania pamięcią
  • próba dostępu do nieistniejącego adresu pamięci (poza przestrzenią adresową procesu)
  • [9]} próba uzyskania dostępu do pamięci, do której program nie ma praw (takich jak struktury jądra w kontekście procesu)
  • próba zapisu pamięci tylko do odczytu (np. segment kodu)

Te z kolei są często spowodowane błędami programowania, które skutkują nieprawidłową pamięcią dostęp:

  • Dereferencja lub przypisanie do niezainicjowanego wskaźnika (wild pointer, który wskazuje na losowy adres pamięci)

  • Dereferencja lub przypisanie do zwolnionego wskaźnika (zwisający wskaźnik, który wskazuje na pamięć, która została zwolniona/dealokowana/usunięta)

  • Przepełnienie bufora.

  • Przepełnienie stosu.

  • Próba uruchomienia programu, który nie kompiluje się poprawnie. (Niektóre Kompilatory wypisują plik wykonywalny plik pomimo obecności błędów w czasie kompilacji.)

 10
Author: Roy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-09 15:36:04

Błąd segmentacji występuje, gdy proces (uruchomiona instancja programu) próbuje uzyskać dostęp do adresu pamięci tylko do odczytu lub zakresu pamięci, który jest używany przez inny proces lub uzyskać dostęp do nieistniejącego (nieprawidłowego) adresu pamięci. Problem zwisającego odniesienia (wskaźnika) oznacza, że próba uzyskania dostępu do obiektu lub zmiennej, której zawartość została już usunięta z pamięci, np.:

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here
 9
Author: Sohail xIN3N,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-10 22:34:36

W prostych słowach: błąd segmentacji to system operacyjny wysyłający sygnał do programu mówiąc, że wykrył nielegalny dostęp do pamięci i przedwcześnie kończy program, aby zapobiec pamięć przed uszkodzeniem.

 7
Author: Canatto Filipe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 13:43:55

Istnieje kilka dobrych wyjaśnień "błędu segmentacji" w odpowiedziach, ale ponieważ z błędem segmentacji często jest zrzut zawartości pamięci, chciałem podzielić się, gdzie relacja między "rdzeniem wyrzuconym" w Błąd segmentacji (rdzeń wyrzucony) i pamięć pochodzi z:

Od około 1955 do 1975 roku-przed pamięcią półprzewodnikową-dominującą technologią w pamięci komputerowej były drobne pączki magnetyczne nawleczone na druty miedziane. Znane były pączki jako "Rdzenie ferrytowe" i pamięć główna znana jako "pamięć rdzeniowa" lub "rdzeń".

Wzięte z tutaj .

 3
Author: Viktor Nonov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-13 18:39:56

"Błąd segmentacji" oznacza, że próbowałeś uzyskać dostęp do pamięci, do której nie masz dostępu.

Pierwszy problem jest z argumentami main. Główną funkcją powinna być int main(int argc, char *argv[]), a przed uzyskaniem dostępu do argv[1] należy sprawdzić, czy argc ma wartość co najmniej 2.

Również, ponieważ przekazujesz zmiennoprzecinkowy do printf (który, nawiasem mówiąc, jest konwertowany na podwójny podczas przekazywania do printf), powinieneś użyć specyfikacji formatu %f. Specyfikator formatu %s jest dla ciągów ('\0' - zakończony tablice znaków).

 3
Author: PHP Worm...,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-06 11:31:20

Błąd segmentacji lub naruszenie dostępu występuje, gdy program próbuje uzyskać dostęp do lokalizacji pamięci, która nie istnieje, lub próbuje uzyskać dostęp do lokalizacji pamięci w sposób, który jest niedozwolony.

 /* "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;

Tutaj [1000] nie istnieje, więc występuje segfault.

Przyczyny błędu segmentacji:

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).
 2
Author: Mohit Rohilla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-08 16:14:05

Jest wystarczająco dużo definicji błędów segmentacji, chciałbym przytoczyć kilka przykładów, na które natknąłem się podczas programowania, które mogą wydawać się głupawymi błędami, ale będą tracić dużo czasu.

  1. Można uzyskać błąd segmentacji w przypadku poniżej, podczas gdy argument type mismatch w printf

    #include<stdio.h> int main(){
    int a = 5; printf("%s",a); return 0; }

Wyjście: Segmentation Fault (SIGSEGV)

  1. Gdy zapomniałeś przydzielić pamięć do wskaźnika, ale próbujesz go użyć.

     #include<stdio.h> 
     typedef struct{
       int a;
     }myStruct;   
    int main(){
      myStruct *s;
      /* few lines of code */
      s->a = 5;
      return 0;
    }
    

Wyjście : Segmentation Fault (SIGSEGV)

 2
Author: NPE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-10 15:44:29

Proste znaczenie Segmentation fault jest takie, że próbujesz uzyskać dostęp do jakiejś pamięci, która nie należy do ciebie. Segmentation fault występuje, gdy próbujemy odczytywać i / lub zapisywać zadania w Miejscu Pamięci tylko do odczytu lub próbujemy zwolnić pamięć. Innymi słowy, możemy to wyjaśnić jako pewnego rodzaju uszkodzenie pamięci.

Poniżej wymieniam typowe błędy popełniane przez programistów, które prowadzą do Segmentation fault.

  • użyj scanf() w niewłaściwy sposób(zapomniałem umieścić &).
int num;
scanf("%d", num);// must use &num instead of num
  • użyj wskaźników w źle sposób.
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.
  • modyfikowanie literału łańcuchowego (wskaźnik próbuje zapisać lub zmodyfikować pamięć tylko do odczytu.)
char *str;  

//Stored in read only part of data segment
str = "GfG";      

//Problem:  trying to modify read only memory
*(str+1) = 'n';
  • spróbuj dotrzeć przez adres, który jest już wolny.
// 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; 
  • Stack Overflow -: kończy się pamięć na stosie
  • dostęp do tablicy poza granicami "
  • używaj niewłaściwych specyfikacji formatu podczas używania printf() i scanf() '
 1
Author: Kalana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-13 13:05:06

Rozważ następujące fragmenty kodu,

SNIPPET 1

int *number = NULL;
*number = 1;

SNIPPET 2

int *number = malloc(sizeof(int));
*number = 1;

Zakładam, że znasz znaczenie funkcji: malloc() i sizeof() jeśli zadajesz to pytanie.

Teraz, gdy to jest ustalone, Fragment 1 spowoduje błąd segmentacji. natomiast SNIPPET 2 nie.

Oto dlaczego.

Pierwsza linia fragmentu pierwszego tworzy zmienną (*number) do przechowywania adresu innej zmiennej, ale w tym przypadku jest inicjalizowana za NULL. z drugiej strony, Drugi wiersz fragmentu drugiego tworzy tę samą zmienną(*number), która przechowuje adres innej i w tym przypadku otrzymuje adres pamięci (ponieważ malloc () jest funkcją w C/C++, która zwraca adres pamięci komputera)

Chodzi o to, że nie można wkładać wody do miski, która nie została kupiona lub miski, która została kupiona, ale nie została przez Ciebie dopuszczona do użytku. Gdy próbujesz to zrobić, komputer zostaje zaalarmowany i rzuca błąd SegFault.

Błędy te należy napotkać tylko w językach, które są blisko niskiego poziomu, takich jak C / C++. W innych językach wysokiego poziomu istnieje abstrakcja, która zapewnia, że nie popełnisz tego błędu.

Ważne jest również, aby zrozumieć, że błąd segmentacji nie jest specyficzny dla języka.

 1
Author: Felix Favour Chinemerem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-15 10:17:41