Che cos'è un errore di segmentazione? È diverso in C e C ++? In che modo sono correlati guasti di segmentazione e puntatori pendenti?
NullPointerException
.
Che cos'è un errore di segmentazione? È diverso in C e C ++? In che modo sono correlati guasti di segmentazione e puntatori pendenti?
NullPointerException
.
Risposte:
L'errore di segmentazione è un tipo specifico di errore causato dall'accesso alla memoria che "non ti appartiene". È un meccanismo di supporto che ti impedisce di corrompere la memoria e di introdurre bug di memoria difficili da eseguire il debug. Ogni volta che ottieni un segfault sai che stai facendo qualcosa di sbagliato con la memoria - accedere alla variabile che è già stata liberata, scrivere su una parte di sola lettura della memoria, ecc. L'errore di segmentazione è essenzialmente lo stesso nella maggior parte delle lingue che ti permettono di fare confusione la gestione della memoria, non vi è alcuna differenza principale tra i segfault in C e C ++.
Esistono molti modi per ottenere un segfault, almeno nei linguaggi di livello inferiore come C (++). Un modo comune per ottenere un segfault è di dereferenziare un puntatore nullo:
int *p = NULL;
*p = 1;
Un altro segfault si verifica quando si tenta di scrivere su una parte della memoria contrassegnata come di sola lettura:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
Puntatore ciondolante punta a una cosa che non esiste più, come qui:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
Il puntatore p
pende perché indica la variabile di carattere c
che ha cessato di esistere dopo la fine del blocco. E quando provi a dereferenziare un puntatore penzolante (come *p='A'
), probabilmente otterrai un segfault.
c
è locale, significa che è stato inserito nello stack dopo {
e pop-ed dopo }
. il puntatore pendente è solo un riferimento a un offset che è ora fuori dallo stack. ecco perché modificarlo in un semplice programma non attiverà mai alcun segfault. d'altra parte può portare alla segfault in un caso d'uso più complesso, in cui altre chiamate di funzione potrebbero far crescere lo stack e contenere i dati a cui punta il puntatore penzolante. scrivere su quei dati (variabili locali) porterebbe a comportamenti indefiniti (segfault & Co)
SIGSEGV
, quindi non mi aspetto che un tale segnale si rovini con lo stack.
Vale la pena notare che l'errore di segmentazione non è causato dall'accesso diretto a un'altra memoria di processo (questo è ciò che sento a volte), poiché semplicemente non è possibile. Con la memoria virtuale ogni processo ha il suo spazio di indirizzi virtuale e non c'è modo di accedervi con qualsiasi valore di puntatore. Un'eccezione a questo può essere librerie condivise che sono lo stesso spazio di indirizzi fisico mappato su (possibilmente) indirizzi virtuali e memoria del kernel diversi che sono persino mappati allo stesso modo in ogni processo (per evitare il flushing TLB su syscall, penso). E cose come shmat;) - questi sono quelli che considero un accesso "indiretto". Tuttavia, è possibile verificare che si trovino di solito molto distanti dal codice di processo e che di solito siamo in grado di accedervi (ecco perché sono lì,
Tuttavia, può verificarsi un errore di segmentazione in caso di accesso alla nostra memoria (di processo) in modo improprio (ad esempio, tentando di scrivere nello spazio non scrivibile). Ma la ragione più comune per questo è l'accesso alla parte dello spazio di indirizzi virtuale che non è affatto mappata a quella fisica.
E tutto questo rispetto ai sistemi di memoria virtuale.
Un errore di segmentazione è causato da una richiesta per una pagina che il processo non ha elencato nella sua tabella descrittiva o da una richiesta non valida per una pagina che ha elencato (ad esempio una richiesta di scrittura su una pagina di sola lettura).
Un puntatore pendente è un puntatore che può o meno puntare a una pagina valida, ma punta a un segmento di memoria "imprevisto".
Ad essere onesti, come hanno già detto altri poster, Wikipedia ha un ottimo articolo su questo, quindi dai un'occhiata qui. Questo tipo di errore è molto comune e spesso chiamato altre cose come violazione di accesso o errore di protezione generale.
Non sono diversi in C, C ++ o in qualsiasi altro linguaggio che consenta i puntatori. Questi tipi di errori sono generalmente causati da puntatori che lo sono
Secondo Wikipedia:
Si verifica un errore di segmentazione quando un programma tenta di accedere a una posizione di memoria a cui non è consentito accedere o tenta di accedere a una posizione di memoria in un modo non consentito (ad esempio, tentando di scrivere in una posizione di sola lettura, oppure per sovrascrivere parte del sistema operativo).
L'errore di segmentazione è anche causato da guasti hardware, in questo caso le memorie RAM. Questa è la causa meno comune, ma se non trovi un errore nel tuo codice, forse un memtest potrebbe aiutarti.
La soluzione in questo caso, cambia la RAM.
modificare:
Qui c'è un riferimento: errore di segmentazione dell'hardware
L'errore di segmentazione si verifica quando un processo (esecuzione dell'istanza di un programma) sta tentando di accedere all'indirizzo di memoria di sola lettura o all'intervallo di memoria utilizzato da un altro processo o accedere all'indirizzo di memoria inesistente (non valido). Il problema Dangling Reference (puntatore) indica che il tentativo di accedere a un oggetto o una variabile il cui contenuto è già stato eliminato dalla memoria, ad esempio:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
La pagina Segmentation_fault di Wikipedia ha una bella descrizione a riguardo, indicando solo le cause e le ragioni. Dai un'occhiata al wiki per una descrizione dettagliata.
Nell'informatica, un errore di segmentazione (spesso abbreviato in segfault) o una violazione di accesso è un errore generato dall'hardware con protezione della memoria, che notifica a un sistema operativo (OS) una violazione dell'accesso alla memoria.
Di seguito sono riportate alcune cause tipiche di un errore di segmentazione:
Questi a loro volta sono spesso causati da errori di programmazione che provocano un accesso alla memoria non valido:
Dereferenziazione o assegnazione a un puntatore non inizializzato (puntatore jolly, che punta a un indirizzo di memoria casuale)
Dereferenziazione o assegnazione a un puntatore liberato (puntatore pendente, che punta alla memoria che è stata liberata / deallocata / eliminata)
Un buffer overflow.
Un overflow dello stack.
Tentativo di eseguire un programma che non viene compilato correttamente. (Alcuni compilatori genereranno un file eseguibile nonostante la presenza di errori durante la compilazione.)
In parole semplici: errore di segmentazione è il sistema operativo che invia un segnale al programma dicendo che ha rilevato un accesso illegale alla memoria e sta terminando prematuramente il programma per evitare che la memoria venga danneggiata.
"Errore di segmentazione" significa che hai tentato di accedere alla memoria a cui non hai accesso.
Il primo problema riguarda i tuoi argomenti di main. La funzione principale dovrebbe essere int main(int argc, char *argv[])
e dovresti controllare che argc sia almeno 2 prima di accedere ad argv [1].
Inoltre, poiché stai passando un float a printf (che, a proposito, viene convertito in doppio quando passi a printf), dovresti usare l'identificatore di formato% f. L'identificatore di formato% s è per stringhe (array di caratteri con terminazione '\ 0').
Si verifica un errore di segmentazione o una violazione di accesso quando un programma tenta di accedere a una posizione di memoria che non esiste o tenta di accedere a una posizione di memoria in un modo non consentito.
/* "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;
Qui non [1000] non esisto, quindi si verifica segfault.
Cause dell'errore di segmentazione:
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).
Ci sono molte buone spiegazioni di "Errore di segmentazione" nelle risposte, ma poiché con errore di segmentazione spesso c'è un dump del contenuto della memoria, volevo condividere dove la relazione tra la parte "core dumped" nell'errore di segmentazione (core dumped) e la memoria viene da:
Dal 1955 al 1975 circa - prima della memoria dei semiconduttori - la tecnologia dominante nella memoria del computer utilizzava piccole ciambelle magnetiche infilate su fili di rame. Le ciambelle erano conosciute come "nuclei di ferrite" e memoria principale così conosciuta come "memoria centrale" o "nucleo".
Tratto da qui .
Ci sono abbastanza definizioni di errore di segmentazione, vorrei citare alcuni esempi che ho riscontrato durante la programmazione, che potrebbero sembrare errori sciocchi, ma perderanno molto tempo.
è possibile ottenere un errore di segmentazione nel caso seguente mentre il tipo argumet non corrisponde a printf
#include<stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
produzione : Segmentation Fault (SIGSEGV)
quando hai dimenticato di allocare memoria a un puntatore, ma provi a usarlo.
#include<stdio.h>
typedef struct{
int a;
}myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
produzione : Segmentation Fault (SIGSEGV)
Il semplice significato di Segmentation fault
è che stai provando ad accedere ad una memoria che non ti appartiene. Segmentation fault
si verifica quando tentiamo di leggere e / o scrivere attività in una posizione di memoria di sola lettura o tentiamo di liberare memoria. In altre parole, possiamo spiegarlo come una sorta di corruzione della memoria.
Di seguito menziono errori comuni commessi da programmatori che portano a Segmentation fault
.
scanf()
in modo errato (dimenticato di mettere &
).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()
e scanf()
"