2011-01-30 17 views
7

A veces, los errores pueden causar una excepción de violación de acceso a memoria.Exactamente cómo se desencadena una excepción de infracción de acceso

¿Cómo se desencadena exactamente esta excepción? ¿Qué mecanismo funciona detrás de las escenas?

¿Es necesario el apoyo de la CPU (a partir de lo que la CPU?)/Desde el sistema operativo (a partir de qué versión?)/Del compilador (a partir de qué versión?)

Editar:

Un escenario específico que quiero entender mejor:

El siguiente código puede causar una excepción de violación de acceso.

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

Supongo que czXXX apunta a un bloque de memoria de solo lectura, pero ¿qué ocurre exactamente?

Respuesta

11

violaciónes de acceso a memoria son un gran tema :)

The Protection of Information in Computer Systems (desde 1973 :) establece fuera de un mecanismo de segmentos, en donde los procesos se asignan una basey una obligado; cualquier intento de acceder a la memoria fuera del rango base:base+bound significaba que el programa había hecho algo tonto y debería ser eliminado.

La línea de procesadores 80x86 implementa soporte de segmento básico, y el kernel de seguridad GEMSOS es un kernel de sistema operativo certificado por A1 basado en este mecanismo.

Pero los segmentos no son muy dinámicos, y casi todos los sistemas operativos modernos son sistemas paging, esa página en memoria cuando no está disponible. Esto depende de que la CPU tenga una unidad de administración de memoria MMU, que comprueba todos los accesos a la memoria para detectar los privilegios correctos y la presencia/ausencia de la asignación de memoria correcta. Cuando un proceso intenta acceder a la memoria que no está asignada actualmente a la RAM, la MMU indica a la CPU que se ha producido un error y la CPU suspende el proceso para cargar la página de memoria solicitada desde el disco. (O, si la memoria no se debe asignar para el proceso, decir que intenta acceder a 0x0 o alguna posición de memoria aleatoria que no ha sido asignada con mmap o similares primitivas de memoria asignación, mata el proceso.)

Intel 80386 fue el primer chip de Intel que admite paginación, por lo que el "Modo encanalizado 386" de Windows 3.1 fue por lo que es mucho mejor que el modo 286.

Los compiladores no están realmente involucrados, pero la CPU, MMU y el kernel del sistema operativo deben funcionar todos juntos.

+0

¿Qué ocurre si la memoria RAM y el disco están llenos? –

+0

@Scott 混合 理论 es normal que la RAM esté llena, o casi llena: la memoria RAM no utilizada se desperdicia RAM. Dado que el rendimiento se degrada cuanto más la computadora debe usar el espacio de intercambio, normalmente la gente intentará ejecutar solo el software que se ajuste a la memoria. Una vez que el espacio de intercambio está lleno, el kernel comenzará a devolver los errores para las asignaciones de memoria o eliminará los procesos completos para liberar espacio. Busque "OOM Killer" para más detalles sobre eso. – sarnold

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

En realidad, su ejemplo tiene un comportamiento indefinido según el estándar;) – undercover

6

En la arquitectura x86 (y la mayoría de las demás también), esto se inicia desde la unidad de gestión de memoria MMU. La MMU se usa para traducir direcciones de memoria virtual a direcciones de memoria física. Si se realiza una solicitud para acceder a una dirección no válida (0x00000000 o algo demasiado alto), la MMU interceptará (interrumpirá) el sistema operativo (esto se hace para cada acceso que no esté en el TLB (Translate Lookaside Buffer - la traducción MMU "caché ")). Aquí el SO podrá decir que este es un acceso a la memoria ilegal, y propagarse a la aplicación del usuario a través del mecanismo dependiente del sistema operativo (señales en Linux (SIGSEGV), no estoy lo suficientemente familiar con Windows como para decir cómo se hace en eso).

Esta función está disponible para cualquier CPU, sistema operativo y compilador modernos. El requisito más básico es una MMU, que está presente en todas las CPU incrustadas menos básicas. Dudo que haya una PC funcionando actualmente que no sea compatible con esto.

Editar:

Después de la OP editar, cuando se utiliza una cadena literal, la memoria se coloca en el segmento .text del ejecutable. Aquí es donde se sientan el código binario y los valores constantes. Naturalmente, en la mayoría de los sistemas operativos esto es de solo lectura (especialmente en Linux con varias mejoras de seguridad). Cuando intenta cambiar el valor de una cadena literal, básicamente intenta escribir en una memoria de solo lectura, lo que provoca una infracción de acceso. Nuevamente, esto es capturado por la MMU que ve un comando de escritura en una dirección de memoria de solo lectura.

+1

El mecanismo dependiente del sistema operativo se denomina "excepciones estructuradas" en Windows: http://msdn.microsoft.com/en-us/library/ms680657%28v=vs .85% 29.aspx – sbk

2

Al intentar acceder a una dirección de memoria, el equipo pasa por varias etapas:

  • Si la dirección es parte del segmento de memoria actual, se concede el acceso.
  • De lo contrario, si el segmento de la dirección está en la memoria con el permiso de acceso apropiado, se concede el acceso.

Si la dirección no está en la memoria, la CPU generará una excepción de comprobación de memoria. En este punto, el sistema operativo toma el control.

  • Si el segmento está disponible en la memoria virtual con permiso de acceso adecuado, que se carga en memoria y se asigna al administrador de memoria virtual; el acceso se otorga.

Si, en este punto, la memoria no está disponible, hay una de dos posibilidades. O bien la dirección no está disponible, o no tiene los permisos que necesita (por ejemplo, tratando de escribir en la memoria de solo lectura). En este caso, el sistema operativo pasará la violación de acceso al proceso.

En cuanto a las versiones de CPU y SO, este es cualquier sistema que permite la memoria virtual. No sé los detalles de esto.

1

Memoria violación de acceso se puede producir aquí también:

delete pSample; 

//again deleting the same memory! 
delete pSample; 

Para tales casos, la excepción se eleva desde el modelo de memoria del sistema operativo. ¡Principalmente es el sistema operativo cuyo trabajo es validar el acceso a la memoria desde cualquier proceso!

2

Todas estas respuestas explican muy bien lo que sucede a nivel de procesador. Como se mencionó, una vez que el procesador provoca una interrupción en el sistema operativo, las cosas cambian con diferentes sistemas operativos.

Windows utiliza un mecanismo conocido como "Structured exceptions". Es muy importante no confundir esto con las excepciones de C++, son diferentes. Las excepciones estructuradas conceptualmente funcionan de la misma manera que las excepciones de C++, ya que desenrollan la pila buscando un controlador. Dado que las excepciones estructuradas son independientes del idioma, hacen no llaman destructores o hacer cualquier limpieza.

excepciones estructurados pueden ser capturados con

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

Se advirtió sin embargo, que una vez que llegue un estructurado de excepciones, su programa tiene ya se estrelló, lo que no hay manera de cuerdo a 'recuperar'.

Más información en SEH.

Cuestiones relacionadas