Falles de segmentació en C o C++ és un error que es produeix quan un programa intenta accedir a una ubicació de memòria a la qual no té permís per accedir. En general, aquest error es produeix quan es viola l'accés a la memòria i és un tipus d'error de protecció general. Segfaults són l'abreviatura de les falles de segmentació.
El abocador de nuclis fa referència a l'enregistrament de l'estat del programa, és a dir, els seus recursos a la memòria i al processador. Intentar accedir a la memòria inexistent o a la memòria que està sent utilitzada per altres processos també provoca l'error de segmentació que condueix a un abocament del nucli.
Un programa té accés a regions específiques de memòria mentre s'executa. En primer lloc, la pila s'utilitza per contenir les variables locals de cada funció. A més, podria tenir memòria assignada en temps d'execució i desada al munt (nou en C++ i també podeu escoltar-la anomenada botiga gratuïta ). L'única memòria a la qual el programa pot accedir és la pròpia (la memòria esmentada anteriorment). Es produirà un error de segmentació per qualsevol accés fora d'aquesta regió.
L'error de segmentació és un tipus específic d'error causat per accedir a la memòria no et pertany :
- Quan un fragment de codi intenta fer una operació de lectura i escriptura en una ubicació de només lectura de la memòria o un bloc de memòria alliberat, es coneix com a fallada de segmentació.
- És un error que indica una corrupció de la memòria.
Escenaris de falla de segmentació comuns
En un error de segmentació, un programa intenta accedir a la memòria que no està autoritzada per accedir-hi o que no existeix. Alguns escenaris habituals que poden provocar errors de segmentació són:
- Modificació d'un literal de cadena
- Accés a una adreça que està alliberada
- Accés a límits d'índex fora de matriu
- Ús inadequat de scanf()
- Desbordament de pila
- Desreferenciació del punter no inicialitzat
1. Modificació d'un literal de cadena
Els literals de cadena s'emmagatzemen a la secció de només lectura de la memòria. És per això que el programa següent pot fallar (ofereix un error de segmentació) perquè la línia *(str+1) = 'n' intenta escriure una memòria de només lectura.
Exemple:
C
// C program to demonstrate segmentation fault> // by modifying a string literal> #include> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation fault> // by modifying a string literal> #include> using> namespace> std;> int> main()> {> >char>* str;> >// Stored in read only part of data segment //> >str =>'GfG'>;> >// Problem: trying to modify read only memory //> >*(str + 1) =>'n'>;> >return> 0;> }> |
>
>
Sortida
temps d'espera: l'ordre supervisada ha volcat el nucli
/bin/bash: línia 1: 32 Temps d'espera d'error de segmentació 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.
Consulteu Emmagatzematge per a cadenes en C per obtenir més detalls.
2. Accés a una adreça que està alliberada
Aquí, al codi següent, el punter p es desfereix després d'alliberar el bloc de memòria, cosa que el compilador no permet. Aquests punters s'anomenen punters penjants i produeixen errors de segment o terminació anormal del programa en temps d'execució.
Exemple:
C
// C program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> #include> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(8);> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// core dump/segmentation fault> >// as now this statement is illegal> >*p = 110;> >printf>(>'%d'>, *p);> >return> 0;> }> |
pitó camelcase
>
>
C++
// C++ program to demonstrate segmentation fault> // by Accessing an address that is freed> #include> using> namespace> std;> int> main(>void>)> {> >// allocating memory to p> >int>* p = (>int>*)>malloc>(>sizeof>(>int>));> >*p = 100;> >// deallocated the space allocated to p> >free>(p);> >// segmentation fault> >// as now this statement is illegal> >*p = 110;> >return> 0;> }> |
>
>
Sortida
Segmentation Fault>
3. Accés a l'índex de matriu fora dels límits
En C i C++, l'accés a un índex de matriu fora dels límits pot provocar un error de segmentació o un altre comportament no definit. No hi ha cap comprovació de límits per a les matrius en C i C++. Encara que en C++, l'ús de contenidors com el mètode std::vector::at() o amb una instrucció if() pot evitar errors fora de límit.
Exemple:
C
// C program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> int> main(>void>)> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> (0);> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when array out of bound is accessed.> #include> using> namespace> std;> int> main()> {> >int> arr[2];> >// Accessing out of bound> >arr[3] = 10;> >return> 0;> }> |
>
>
Sortida
Segmentation Faults>
4. Ús inadequat de scanf()
La funció scanf() espera l'adreça d'una variable com a entrada. Aquí, en aquest programa, n pren un valor de 2 i assumeix la seva adreça com a 1000. Si passem n a scanf(), l'entrada obtinguda des de STDIN es col·loca a la memòria no vàlida 2 que hauria de ser 1000. Això provoca una corrupció de la memòria que condueix a un error de segmentació.
Exemple:
C
// C program to demonstrate segmentation> // fault when value is passed to scanf> #include> int> main()> {> >int> n = 2;> >scanf>(>'%d'>, n);> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when value is passed to scanf> #include> using> namespace> std;> int> main()> {> >int> n = 2;> >cin>> n;> >return> 0;> }> |
>
>
Sortida
Segementation Fault>
5. Desbordament de pila
No és un problema relacionat amb el punter, fins i tot el codi pot no tenir un sol punter. És perquè es queda sense memòria a la pila. També és un tipus de corrupció de memòria que pot ocórrer a causa de la gran mida de la matriu, un gran nombre de trucades recursives, moltes variables locals, etc.
Exemple:
C
// C program to illustrate the> // segmentation fault due to> // stack overflow> #include> int> main()> {> >int> arr[2000000000];> >return> 0;> }> |
>
>
C++
// C++ program to illustrate> // the segmentation fault> // due to stack overflow> #include> using> namespace> std;> int> main()> {> >int> array[2000000000];> >return> 0;> }> |
>
>
Sortida
Segmentation Fault>
6. Desbordament del buffer
Si les dades que s'emmagatzemen a la memòria intermèdia són més grans que la mida assignada de la memòria intermèdia, es produeix un desbordament de la memòria intermèdia que condueix a l'error de segmentació. La majoria dels mètodes del llenguatge C no realitzen la comprovació d'enllaços, de manera que el desbordament de la memòria intermèdia es produeix amb freqüència quan ens oblidem d'assignar la mida necessària a la memòria intermèdia.
Exemple:
C
// C program to illustrate the> // segementation fault due to> // buffer overflow> #include> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }> |
>
>
C++
// C++ program to illustrate the> // segementation fault due to> // buffer overflow> #include> using> namespace> std;> int> main()> {> >char> ref[20] =>'This is a long string'>;> >char> buf[10];> >sscanf>(ref,>'%s'>, buf);> >return> 0;> }> |
>
>
Sortida
Segmentation Fault>
7. Desreferenciar un punter no inicialitzat o NULL
És un error de programació comú desfer de referència a un punter no inicialitzat ( punter salvatge ), que pot provocar un comportament no definit. Quan s'utilitza un punter en un context que el tracta com un punter vàlid i accedeix al seu valor subjacent, tot i que no s'ha inicialitzat per apuntar a una ubicació de memòria vàlida, es produeix aquest error. D'això es poden produir corrupcions de dades, errors de programa o errors de segmentació. Depenent del seu entorn i de l'estat a l'hora de desreferenciar, els punters no inicialitzats poden donar resultats diferents.
Com sabem, el punter NULL no apunta a cap ubicació de memòria, de manera que desreferenciar-lo donarà lloc a un error de segmentació.
Exemple:
C
string convertir a int a Java
// C program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >printf>(>'%d %d'>, *ptr, *nptr);> >return> 0;> }> |
>
>
C++
// C++ program to demonstrate segmentation> // fault when uninitialized pointer> // is accessed> #include> using> namespace> std;> int> main()> {> >int>* ptr;> >int>* nptr = NULL;> >cout << *ptr <<>' '> << *nptr;> >return> 0;> }> |
>
>
Sortida
Segmentation Fault>
Com solucionar els errors de segmentació?
Podem solucionar els errors de segmentació tenint cura de les causes esmentades:
- Eviteu modificar literals de cadena.
- Anar amb compte a l'hora d'utilitzar punters, ja que són una de les causes més freqüents.
- Tenint en compte la mida de la memòria intermèdia i la pila abans d'emmagatzemar les dades per evitar el desbordament de la memòria intermèdia o la pila.
- Comprovació dels límits abans d'accedir als elements de la matriu.
- Utilitzeu scanf() i printf() amb cura per evitar especificadors de format incorrectes o desbordament de memòria intermèdia.
En general, la causa de l'error de segmentació és accedir a la memòria que no us pertany en aquest espai. Mentre evitem fer-ho, podem evitar l'error de segmentació. Si no podeu trobar l'origen de l'error fins i tot després de fer-ho, es recomana utilitzar un depurador, ja que condueix directament al punt d'error del programa.