2009-04-19 5 views
6

Hay una publicación de Raymond Chen, donde he tells how bad IsBadXxxPtr function is by eating guard page exception.¿Salvo excepciones de página en Delphi?

No entiendo muy bien cómo se aplica a Delphi. ¿Quién y cómo debería normalmente (es decir, sin llamar a IsBadXxxPtr) procesar esta excepción? Sé que Delphi inserta un código, que (por ejemplo) accede a una memoria para grandes arreglos estáticos, exactamente por esta razón: para expandir la pila.

Pero si se genera una excepción en la página de guardia: ¿quién la manejará en una aplicación Delphi? ¿No puedo meterme accidentalmente con él usando try/except de manera inapropiada? ¿El depurador de Delphi me notificará sobre estas excepciones?

+1

Copia de seguridad un momento. ¿Para qué necesita llamar a una de las funciones de IsBadXXXPtr? – jmucchiello

+0

No necesito nada de IsBadXXXPtr (estoy de acuerdo con Raymond, es mejor bloquearse en estos casos). Acabo de enterarme de que no sé cómo se maneja esta situación en Delphi. Es por eso que pregunto, solo por curiosidad. – Alex

+0

¿Qué código "conoce" inserta Delphi para expandir la pila al acceder a grandes arreglos estáticos? Nunca he visto nada por el estilo. –

Respuesta

13

El manejo de excepciones estructuradas de Windows (SEH) tiene una estructura de dos fases. Cuando se produce una excepción, Windows busca primero un controlador para la excepción siguiendo la cadena de manejador de excepciones registradas (cuyo encabezado está almacenado en fs: [0] en x86, es decir, el primer dword en el segmento apuntado por el segmento FS) registrarse - toda esa fea lógica de desplazamiento de segmento de 16 bits no desapareció en 32 bits, simplemente se volvió menos relevante).

La búsqueda se realiza llamando a una función con una bandera particular, un puntero que se almacena en cada marco de excepción en la pila. fs: [0] apunta al cuadro superior. Cada cuadro apunta al cuadro anterior. En última instancia, el último cuadro de la lista es uno que ha sido proporcionado por el sistema operativo (este controlador mostrará un cuadro de diálogo de bloqueo de aplicación si lo alcanza una excepción no controlada).

Estas funciones normalmente verifican el tipo de la excepción y devuelven un código para indicar qué hacer. Uno de los códigos que pueden devolverse es básicamente "ignorar esta excepción y continuar". Si Windows ve esto, restablecerá el puntero de la instrucción al punto de la excepción y reanudará la ejecución. Otro código indica que este marco de excepción debe manejar la excepción dada. Un tercer código es "No voy a detectar esta excepción, sigo buscando". Windows sigue llamando a estas funciones de filtro de excepciones hasta que encuentra una que maneje la excepción de una manera u otra.

Si Windows encuentra uno que maneja la excepción al capturarlo, procederá a desenrollar la pila de nuevo a ese controlador, que consiste en llamar a todas las funciones nuevamente, solo pasando una bandera diferente. Es en este punto que las funciones ejecutan la lógica finally, hasta que el controlador que ejecuta la lógica except.

Sin embargo, con la excepción de protector de página de pila, el proceso es diferente. Ninguno de los manejadores de excepciones del idioma elegirá manejar esta excepción, porque de lo contrario se rompería el mecanismo de crecimiento de la pila.En su lugar, la búsqueda de filtros se filtra hasta el manejador de excepción base proporcionado por el sistema operativo, que aumenta la asignación de la pila al comprometer la memoria apropiada y luego devuelve el código de retorno apropiado para indicar que el sistema operativo debe continuar donde lo dejó. en lugar de desenrollar la pila.

La herramienta y la infraestructura de depuración están diseñadas para permitir que estas excepciones particulares funcionen correctamente, por lo que no tiene que preocuparse por su manejo.

Puede leer más sobre SEH en Matt Pietrek's excellent article in MSJ from over a decade ago.

+0

En Delphi, es imposible especificar el resultado "ignorar esto y continuar", ¿no es así? Por lo tanto, no podría configurar una página de protección en Delphi aunque quisiera, separada de lo que proporcione el kernel. El lenguaje realmente no expone todo lo que proporciona SEH, y si lo hiciera, Linux y .Net probablemente habrían sido mucho más difíciles de transportar, ¿no? –

+1

Rob: puede especificar lo que desee si configura el marco de excepción usted mismo, que requiere un pequeño ensamblador. Las excepciones de .NET admiten algo llamado filtros de excepción, que se correlacionan con la fase de búsqueda de SEH, pero solo están expuestos en la sintaxis de ILASM y en Visual Basic para .NET, que yo sepa. WRT Linux, no he profundizado en el mecanismo utilizado por dcc, pero es un mecanismo mapeado en PC, y por simplicidad sospecho que no es de dos fases. –

+0

(El mecanismo de excepciones mapeadas para PC en Kylix fue implementado completamente por el compilador y RTL, ya que Linux no tiene un mecanismo de excepción fuera del muy inferior mecanismo de reentrada en el mismo hilo). –

2

Al mirar los comentarios, me parece que el desorden de la "excepción de la página de guardia" tiene lugar completamente dentro del kernel, y no es algo de lo que deba preocuparse desde el espacio del usuario.

Debe recordar que este artículo fue escrito para C++, que no está tan avanzado como Delphi en el frente de administración de memoria. La cuestión punteros sin inicializar es mucho menos de un lío en Delphi que en C/C++, por dos razones:

  1. cheques de Delphi para las variables sin inicializar en tiempo de compilación, que (por cualquier razón) una gran cantidad de compiladores de C tienden a Tener problemas con.
  2. Delphi inicializa toda su memoria dinámica en 0, por lo que no tiene que ocuparse de la basura del montón aleatorio que podría parecer un buen puntero cuando en realidad no lo es. Esto significa que la mayoría de los indicadores incorrectos le dan infracciones de acceso, que son fáciles de depurar, en lugar de fallar silenciosamente y corromper la memoria.
Cuestiones relacionadas