logo

Errore di segmentazione in C/C++

Difetti di segmentazione in C o C++ è un errore che si verifica quando un programma tenta di accedere a una posizione di memoria a cui non dispone dell'autorizzazione per accedere. In genere, questo errore si verifica quando viene violato l'accesso alla memoria ed è un tipo di errore di protezione generale. Segfault sono l'abbreviazione di errori di segmentazione.

IL discarica del nucleo si riferisce alla registrazione dello stato del programma, cioè delle sue risorse in memoria e processore. Anche il tentativo di accedere a memoria inesistente o memoria utilizzata da altri processi provoca l'errore di segmentazione che porta a un core dump.



Un programma ha accesso a specifiche aree di memoria mentre è in esecuzione. Innanzitutto, lo stack viene utilizzato per contenere le variabili locali per ciascuna funzione. Inoltre, potrebbe avere memoria allocata in fase di esecuzione e salvata nell'heap (una novità in C++ e potresti anche sentirlo chiamare negozio gratuito ). L’unica memoria a cui il programma può accedere è la propria (la memoria menzionata in precedenza). Qualsiasi accesso al di fuori di quella regione risulterà un errore di segmentazione.

L'errore di segmentazione è un tipo specifico di errore causato dall'accesso alla memoria non ti appartiene :

  • Quando una parte di codice tenta di eseguire un'operazione di lettura e scrittura in una posizione di sola lettura della memoria o in un blocco di memoria liberato, si parla di errore di segmentazione.
  • È un errore che indica la corruzione della memoria.

Scenari comuni di errore di segmentazione

In un errore di segmentazione, un programma tenta di accedere alla memoria a cui non è autorizzato ad accedere o che non esiste. Alcuni scenari comuni che possono causare errori di segmentazione sono:



  1. Modifica di una stringa letterale
  2. Accesso ad un indirizzo liberato
  3. Accesso ai limiti dell'indice fuori dall'array
  4. Uso improprio di scanf()
  5. Overflow dello stack
  6. Dereferenziamento del puntatore non inizializzato

1. Modifica di una stringa letterale

I valori letterali della stringa vengono archiviati nella sezione di sola lettura della memoria. Questo è il motivo per cui il programma seguente potrebbe bloccarsi (fornisce un errore di segmentazione) perché la riga *(str+1) = 'n' tenta di scrivere una memoria di sola lettura.

Esempio:

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;> }>

>

>

Produzione

timeout: il comando monitorato ha scaricato il core

/bin/bash: riga 1: 32 Timeout errore segmentazione 15 s ./83b16132-8565-4cb1-aedb-4eb593442235 <83b16132-8565-4cb1-aedb-4eb593442235.in

Fare riferimento a Archiviazione per stringhe in C per ulteriori dettagli.

2. Accesso ad un indirizzo liberato

Qui nel codice seguente, il puntatore p viene dereferenziato dopo aver liberato il blocco di memoria, cosa non consentita dal compilatore. Tali puntatori sono chiamati puntatori pendenti e producono errori di segmento o terminazione anomala del programma in fase di esecuzione.

Esempio:

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;> }>

.04 come frazione

>

>

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;> }>

>

>

Produzione

Segmentation Fault>

3. Accesso all'indice dell'array fuori limite

In C e C++, l'accesso a un indice di matrice fuori dai limiti può causare un errore di segmentazione o un altro comportamento indefinito. Non esiste alcun controllo dei limiti per gli array in C e C++. Sebbene in C++, l'uso di contenitori come con il metodo std::vettore::at() o con un'istruzione if(), può prevenire errori fuori limite.

Esempio:

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;> }>

>

>

Produzione

Segmentation Faults>

4. Uso improprio di scanf()

La funzione scanf() prevede l'indirizzo di una variabile come input. Qui in questo programma n assume il valore 2 e assume il suo indirizzo come 1000. Se passiamo n a scanf(), l'input recuperato da STDIN viene inserito nella memoria non valida 2 che dovrebbe invece essere 1000. Ciò provoca il danneggiamento della memoria che porta a un errore di segmentazione.

Esempio:

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;> }>

>

>

Produzione

Segementation Fault>

5. Overflow dello stack

Non è un problema legato al puntatore, anche se il codice potrebbe non avere un singolo puntatore. È a causa dell'esaurimento della memoria nello stack. È anche un tipo di danneggiamento della memoria che può verificarsi a causa delle grandi dimensioni dell'array, di un gran numero di chiamate ricorsive, di molte variabili locali, ecc.

Esempio:

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;> }>

>

>

Comando Linux per zip

Produzione

Segmentation Fault>

6. Overflow del buffer

Se i dati memorizzati nel buffer sono maggiori della dimensione allocata del buffer, si verifica un overflow del buffer che porta all'errore di segmentazione. La maggior parte dei metodi del linguaggio C non eseguono il controllo dei limiti, quindi l'overflow del buffer si verifica frequentemente quando ci dimentichiamo di allocare la dimensione richiesta al buffer.

Esempio:

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;> }>

>

>

Produzione

Segmentation Fault>

7. Dereferenziare un puntatore non inizializzato o NULL

È un errore di programmazione comune dereferenziare un puntatore non inizializzato ( puntatore selvaggio ), che può provocare un comportamento indefinito. Quando un puntatore viene utilizzato in un contesto che lo considera come un puntatore valido e accede al valore sottostante, anche se non è stato inizializzato per puntare a una posizione di memoria valida, si verifica questo errore. Ciò può causare corruzione dei dati, errori di programma o errori di segmentazione. A seconda dell'ambiente e dello stato durante il dereferenziamento, i puntatori non inizializzati possono produrre risultati diversi.

Come sappiamo il puntatore NULL non punta ad alcuna posizione di memoria, quindi dereferenziarlo comporterà un errore di segmentazione.

Esempio:

C




// 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;> }>

>

>

Produzione

Segmentation Fault>

Come correggere gli errori di segmentazione?

Possiamo correggere gli errori di segmentazione prestando attenzione alle cause menzionate:

  • Evitare di modificare i valori letterali delle stringhe.
  • Fare attenzione quando si utilizzano i puntatori poiché sono una delle cause più comuni.
  • Considerare la dimensione del buffer e dello stack prima di archiviare i dati per evitare l'overflow del buffer o dello stack.
  • Controllo dei limiti prima di accedere agli elementi dell'array.
  • Utilizzare scanf() e printf() con attenzione per evitare specificatori di formato errati o overflow del buffer.

Nel complesso, la causa dell'errore di segmentazione è l'accesso alla memoria che non ti appartiene in quello spazio. Finché evitiamo di farlo, possiamo evitare l’errore di segmentazione. Se anche dopo averlo fatto non si riesce a trovare la fonte dell'errore, si consiglia di utilizzare un debugger poiché porta direttamente al punto dell'errore nel programma.