2012-02-12 13 views
10

No es este código:gestor de excepciones

char text[] = "zim"; 
int x = 777; 

Si miro en la pila donde x y el texto se colocan allí salida es:

09 03 00 00 7a 69 6d 00 

Dónde:

  • 09 03 00 00 = 0x309 = 777 < - int x = 777
  • 7a 69 6d 00 = texto de caracteres [] = "zim" (código ASCII)

No es ahora de código con try..catch:

char text[] = "zim"; 
try{ 
    int x = 777; 
} 
catch(int){ 
} 

Pila:

09 03 00 00 **97 85 04 08** 7a 69 6d 00 

Ahora entre texto y x se coloca nuevo valor de 4 bytes. Si agrego otro catch, entonces habrá algo así como:

09 03 00 00 **97 85 04 08** **xx xx xx xx** 7a 69 6d 00 

y así sucesivamente. Creo que este es un valor relacionado con el manejo de excepciones y se usa durante el desenrollado de la pila para encontrar la captura adecuada cuando se lanza la excepción en el bloque try. Sin embargo, la pregunta es, ¿qué es exactamente este valor de 4 bytes (tal vez alguna dirección para la estructura del manejador de excepciones o alguna identificación)?

Uso g ++ 4.6 en la máquina Linux de 32 bits.

+0

Ver [C++ try/throw/catch => código de máquina] (http://stackoverflow.com/questions/1331220/c-try-throw-catch-machine-code), que apunta a http: // www .codeproject.com/Articles/2126/How-aC-compiler-implements-exception-handling –

+3

¿Por qué quieres saberlo? Incluso si le diéramos una respuesta, sería específico del compilador y de esa versión específica del compilador. Entonces, técnicamente no es una pregunta de C++. Es una pregunta sobre g ++ y cómo funciona. Que a menos que realmente te interese escribir extensiones para g ++ es un conocimiento completamente inútil. –

+4

@LokiAstari: g ++ y otros compiladores de C++ para * nix usan el [Itanium ABI] (http://sourcery.mentor.com/public/cxx-abi/abi-eh.html) en la mayoría de las plataformas (con algunas modificaciones que dependen de la plataforma), así que no es * esa * plataforma/compilador específico. Y aún así, es interesante saber cómo se puede implementar la maquinaria de manejo de excepciones. –

Respuesta

5

AFAICT, que es un puntero a una "tabla de desenrollar". Según el the Itanium ABI implementation suggestions, el proceso "[utiliza] una tabla de desenrollado, [para] encontrar información sobre cómo manejar las excepciones que ocurren en esa PC y, en particular, obtener la dirección de la rutina de personalidad para ese rango de direcciones."

La idea detrás de las tablas de desenrollado es que los datos necesarios para desenrollar la pila rara vez se utilizan. Por lo tanto, es más eficiente colocar un puntero en la pila y almacenar el reast de los datos en otra página. En el mejor de los casos, esa página puede permanecer en el disco y ni siquiera necesita cargarse en la RAM. En comparación, el manejo de errores del estilo C a menudo termina en la caché L1 porque está todo en línea.

0

No hace falta decir todo esto depende de la plataforma y etc

Esto puede ser una dirección. Puede apuntar a una sección de código (alguna dirección de manejador) o sección de datos (puntero a una estructura generada en tiempo de compilación con información de marco), o la pila del mismo subproceso (puntero a una tabla generada en tiempo de ejecución información del marco). O también puede ser una basura, debido a un requisito de alineación, que EH puede exigir.

Por ejemplo, en Win32/x86 no hay tal hueco. Para cada función que utiliza el manejo de excepciones (tiene try/catch o __try/__except/__finally u objetos con d'tors) - el compilador genera una estructura EXCEPTION_RECORD que se asigna en la pila (por el código de función de prólogo). Entonces, cada vez que algo cambia dentro de la función (el objeto es creado/destruido, try/catch bloque ingresado/salido) - el compilador agrega una instrucción que modifica esta estructura (más correctamente - modifica su extensión). Pero nada más se asigna en la pila.

Cuestiones relacionadas