2011-01-30 18 views
7

A volte i bug possono causare un'eccezione di violazione di accesso alla memoria.Come viene attivata esattamente un'eccezione di violazione di accesso

In che modo viene attivata esattamente questa eccezione? Quale meccanismo funziona dietro le quinte?

Ha bisogno il supporto della CPU (a partire da quello della CPU?)/Dal sistema operativo (a partire da quale versione?)/Dal compilatore (a partire da quale versione?)

Edit:

Uno scenario specifico che voglio comprendere meglio:

Il seguente codice può causare un'eccezione di violazione di accesso.

TCHAR* czXXX= _T("ABCDEFG"); 
czXXX[0]= 'A'; 

Immagino che czXXX punti a un blocco di memoria di sola lettura, ma cosa succede esattamente?

risposta

11

violazioni di accesso di memoria sono un gran argomento :)

The Protection of Information in Computer Systems (dal 1973 :) stabilisce su un meccanismo di segmenti, dove processi sono assegnati un di base e legato; qualsiasi tentativo di accedere alla memoria al di fuori del range base:base+bound significava che il programma aveva fatto qualcosa di stupido e doveva essere ucciso.

La linea di processori 80x86 implementa il supporto di segmento di base e il kernel di sicurezza GEMSOS è un kernel del sistema operativo certificato A1 basato su questo meccanismo.

Ma i segmenti non sono molto dinamici e quasi tutti i sistemi operativi moderni sono i sistemi paging, quella pagina nella memoria quando non è disponibile. Questo si basa sulla CPU con un'unità di gestione della memoria MMU, che controlla tutti gli accessi alla memoria per i privilegi e la presenza/assenza corrette della mappatura della memoria corretta. Quando un processo tenta di accedere alla memoria che non è attualmente mappata nella RAM, la MMU segnala alla CPU che si è verificato un errore e la CPU sospende il processo per caricare la pagina di memoria richiesta dal disco. (O, se la memoria non deve essere mappata per il processo, dire che tenta di accedere 0x0 o qualche posizione di memoria casuale che non è stata mappata con mmap o similari memoria allocazione primitive, uccide il processo.)

Intel 80386 è stato il primo chip Intel a supportare il paging, motivo per il quale la "Modalità Enchanced 386" di Windows 3.1 era quindi molto meglio della modalità 286.

I compilatori non sono realmente coinvolti, ma la CPU, la MMU e il kernel del sistema operativo devono essere tutti tutti insieme.

+0

Cosa succede se RAM e Disk sono entrambi pieni? –

+0

@Scott 混合 理论 è normale che la RAM sia piena, o quasi completa - RAM non utilizzata è sprecata RAM. Poiché le prestazioni si riducono, più il computer deve utilizzare lo spazio di swap, in genere le persone cercheranno di eseguire solo il software che si adatta alla memoria. Una volta che lo spazio di swap è pieno, il kernel inizierà a restituire errori per allocazioni di memoria o ucciderà interi processi per liberare spazio. Cerca "OOM Killer" per i dettagli su questo. – sarnold

0
void Kaboom() 
{ 
    int* certain_death = NULL; 
    *certain_death = 0; 
} 
+1

In realtà l'esempio ha un comportamento non definito in base allo standard;) – undercover

6

Nell'architettura x86 (e anche nella maggior parte degli altri), questo viene avviato dall'unità di gestione della memoria MMU. La MMU viene utilizzata per tradurre gli indirizzi di memoria virtuale in indirizzi di memoria fisica. Se viene effettuata una richiesta per accedere a un indirizzo non valido (0x00000000 o qualcosa di troppo alto) la MMU intercetterà (interrompe) il sistema operativo (questo è in realtà fatto per ogni accesso non nella cache TLB (Translate Lookaside Buffer - the MMU translation " ")). Qui il sistema operativo sarà in grado di dire che si tratta di un accesso illegale alla memoria e di propagarsi all'applicazione utente tramite il meccanismo dipendente dal sistema operativo (segnali in Linux (SIGSEGV), non ho abbastanza familiarità con Windows per dire come è fatto dentro).

Questa funzione è disponibile per qualsiasi CPU, sistema operativo e compilatore moderni. Il requisito più basilare è una MMU, che è presente in tutte le CPU incorporate tranne quelle più basilari. Dubito che ci sia qualche PC attualmente operativo che non supporta questo.

Edit:

In seguito alla modifica OP, quando si utilizza una stringa letterale, la memoria è collocato nel segmento .text dell'eseguibile. Qui è dove si trovano il codice binario e i valori costanti. Naturalmente, nella maggior parte dei SO questo è di sola lettura (specialmente sotto Linux con vari miglioramenti della sicurezza). Quando si tenta di modificare un valore di una stringa letterale, si sta tentando di scrivere in una memoria di sola lettura, causando una violazione di accesso. Di nuovo, questo viene rilevato dalla MMU che vede un comando di scrittura su un indirizzo di memoria di sola lettura.

+1

Il meccanismo dipendente dal sistema operativo è denominato "eccezioni strutturate" in Windows: http://msdn.microsoft.com/en-us/library/ms680657%28v=vs .85% 29.aspx – sbk

2

Quando si tenta di accedere a un indirizzo di memoria, il computer passa attraverso diverse fasi:

  • Se l'indirizzo è parte del segmento di memoria corrente, l'accesso viene concesso.
  • In caso contrario, se il segmento dell'indirizzo è in memoria con il permesso di accesso appropriato, l'accesso è concesso.

Se l'indirizzo non è in memoria, la CPU genererà un'eccezione di controllo memoria. A questo punto, il sistema operativo prende il sopravvento.

  • Se il segmento è disponibile nella memoria virtuale con il permesso di accesso appropriato, viene caricato in memoria e assegnati al gestore della memoria virtuale; l'accesso è quindi concesso.

Se, a questo punto, la memoria non è disponibile, c'è una delle due possibilità. O l'indirizzo non è disponibile, oppure non hai i permessi necessari (ad esempio, prova a scrivere in memoria di sola lettura). In questo caso, il sistema operativo passerà la violazione di accesso al processo.

Per quanto riguarda le versioni CPU e OS, questo è un sistema che consente la memoria virtuale. Non conosco i dettagli di questo.

1

memoria violazione di accesso può verificarsi anche qui:

delete pSample; 

//again deleting the same memory! 
delete pSample; 

In questi casi, viene sollevata un'eccezione dal modello di memoria del sistema operativo. Principalmente è il sistema operativo il cui compito è quello di convalidare l'accesso alla memoria da qualsiasi processo!

2

Tutte queste risposte spiegano molto bene cosa succede a livello di processore. Come accennato, una volta che il processore solleva un'interruzione all'OS, le cose cambiano con diversi sistemi operativi.

Windows utilizza un meccanismo noto come "Structured exceptions". Molto importante non confondere questo con le eccezioni C++, sono differenti. Eccezioni strutturate concettualmente funzionano allo stesso modo delle eccezioni C++, nel senso che aprono lo stack alla ricerca di un gestore. Dal momento che le eccezioni strutturate sono indipendenti dalla lingua, fanno non distruttori di chiamata o eseguono qualsiasi operazione di pulizia.

eccezioni strutturati possono essere catturati con

__try 
{ 
    //Usual code 
} 
__except(EXCEPTION_EXECUTE_HANDLER) 
{ 
    //Handling code 
} 
__finally 
{ 
    //Cleanup 
} 

Sia avvertito tuttavia, che una volta che si ottiene un Exception strutturato, il programma ha già si è schiantato, quindi non c'è modo sano per 'recuperare'.

Ulteriori informazioni su SEH.

Problemi correlati