technologies reynosa parts mexico empresa autopartes automotive aptiv delphi

reynosa - delphi technologies mexico



Cómo rastrear la infracción de acceso "en la dirección 00000000" (9)

Aquí hay una solución temporal realmente rápida, al menos hasta que reinicie de nuevo, pero se deshará de un acceso persistente. Instalé un programa que funciona bien pero, por alguna razón, hay un punto que no se instaló correctamente en el archivo correcto. Entonces, cuando no puede acceder al archivo, aparece el acceso denegado, pero en lugar de uno solo, intenta iniciarlo, por lo que incluso buscando la ubicación para detenerlo permanentemente, seguirá apareciendo cada vez más cada 3 segundos. Para evitar que esto suceda al menos temporalmente, haga lo siguiente ...

  1. Ctl + Alt + Del
  2. Abra su Administrador de tareas
  3. Anote el nombre del programa que solicita el acceso (puede verlo en la pestaña de su aplicación)
  4. Haga clic en la pestaña Procesos
  5. Desplácese hasta encontrar el proceso que coincida con el nombre del programa y haga clic en él
  6. Haga clic en Terminar proceso

Eso evitará que la ventana aparezca persistentemente, al menos hasta que reinicie. Sé que eso no resuelve el problema, pero como todo, hay un proceso de eliminación y este paso aquí al menos lo hará un poco menos molesto.

Sé cómo crear un archivo .map para rastrear los errores de violación de acceso cuando el mensaje de error incluye una dirección real.

Pero, ¿y si el mensaje de error dice

Access violation at address 00000000. Read of address 00000000.

¿Dónde empiezo a buscar la causa de este problema ...?


Cuando me encuentro con este problema, suelo empezar a buscar en los lugares donde FreeAndNil () o simplemente xxx: = NIL; variables y el código después de eso.

Cuando nada más me ayudó, agregué una función Log () para enviar mensajes de varios lugares sospechosos durante la ejecución, y luego busqué en ese registro para rastrear en qué parte del código aparece la violación de acceso.

Por supuesto, hay muchas más soluciones elegantes disponibles para rastrear estas infracciones, pero si no las tiene a su disposición, el método anticuado de prueba y error funciona bien.


Empiezas a buscar cerca de ese código que sabes que se ejecutó, y dejas de buscar cuando alcanzas el código que sabes que no se ejecutó.

Lo que está buscando es probablemente un lugar donde su programa llama a una función a través de un puntero de función, pero ese puntero es nulo.

También es posible que tengas corrupción en la pila. Es posible que haya sobrescrito la dirección de retorno de una función con cero, y la excepción se produce al final de la función. Compruebe si hay posibles desbordamientos de búfer, y si llama a cualquier función de DLL, asegúrese de haber utilizado la convención de llamadas correcta y el recuento de parámetros.

Este no es un caso ordinario de uso de un puntero nulo, como una referencia de objeto no asignado o PChar. En esos casos, tendrá un valor distinto de cero "en la dirección x ". Como la instrucción se produjo en la dirección cero, sabe que el puntero de instrucción de la CPU no apuntaba a ninguna instrucción válida. Es por eso que el depurador no puede mostrar qué línea de código causó el problema, no hay una línea de código. Debe encontrarlo buscando el código que conduce al lugar donde la CPU saltó a la dirección no válida.

La pila de llamadas aún puede estar intacta, lo que al menos te acercará bastante a tu objetivo. Sin embargo, si tiene daños en la pila, es posible que no pueda confiar en la pila de llamadas.


La respuesta aceptada no cuenta toda la historia.

Sí, cada vez que vea ceros, se trata de un puntero NULL . Eso es porque NULL es por definición cero. Así que llamar a cero NULL puede no decir mucho.

Lo interesante del mensaje que recibes es el hecho de que NULL se menciona dos veces . De hecho, el mensaje que informa se parece un poco a los mensajes que los sistemas operativos de la marca Windows muestran al usuario.

El mensaje dice que la dirección NULL intentó leer NULL . ¿Entonces que significa eso? Específicamente, ¿cómo se lee una dirección?

Normalmente pensamos en las instrucciones en una dirección de lectura y escritura de la memoria en ciertas direcciones. Sabiendo eso nos permite analizar el mensaje de error. El mensaje intenta articular que las instrucciones en la dirección NULL intentaron leer NULL .

Por supuesto, no hay instrucciones en la dirección NULL , es por eso que pensamos que NULL es especial en nuestro código. Pero se puede pensar que cada instrucción comienza con el intento de leerse a sí mismo. Si el registro EIP la CPU está en la dirección NULL , la CPU intentará leer el código de operación para una instrucción de la dirección 0x00000000 ( NULL ). Este intento de leer NULL fallará y generará el mensaje que ha recibido.

En el depurador, observe que EIP equivale a 0x00000000 cuando recibe este mensaje. Esto confirma la descripción que te he dado.

La pregunta entonces es: "¿Por qué mi programa intenta ejecutar la dirección NULL "? Hay tres posibilidades que vienen a la mente:

  • Ha intentado realizar una llamada de función a través de un puntero de función que ha declarado, asignado a NULL , nunca inicializado de otra manera, y está desreferenciando.
  • Del mismo modo, puede estar llamando a un método "abstracto" de C ++ que tiene una entrada NULL en vtable del objeto. Estos se crean en su código con la sintaxis virtual function_name()=0 .
  • En su código, un buffer de pila ha sido desbordado al escribir ceros. Los ceros se han escrito más allá del final del almacenamiento intermedio de la pila, sobre la dirección de devolución conservada. Cuando la función más tarde ejecuta su instrucción ret , el valor 0x00000000 ( NULL ) se carga desde el punto de memoria sobrescrita. Este tipo de error, desbordamiento de pila, es el epónimo de nuestro foro.

Como mencionas que estás llamando a una biblioteca de terceros, señalaré que puede ser una situación de la biblioteca que espera que proporciones un puntero de función que no sea NULL como entrada a alguna API. A veces se conocen como funciones de "devolución de llamada".

Deberá utilizar el depurador para reducir aún más la causa de su problema, pero las posibilidades anteriores le ayudarán a resolver el enigma.


Probablemente sea porque está directa o indirectamente a través de una llamada de biblioteca accediendo a un puntero NULL. En este caso particular, parece que saltó a una dirección NULL, que es un poco más peluda.

En mi experiencia, la manera más fácil de seguir estos pasos es ejecutarlo con un depurador y volcar un seguimiento de la pila.

Alternativamente, puede hacerlo "a mano" y agregar muchos registros hasta que pueda rastrear exactamente qué función (y posiblemente LOC) ocurrió esta violación.

Eche un vistazo a Stack Tracer , que podría ayudarlo a mejorar su depuración.


Seguiré en segundo lugar las herramientas Except y similares, como Eurekalog, pero creo que también puedes avanzar mucho con FastMM. Con el modo de depuración completo habilitado, debería darle algunas pistas de lo que está mal.

De todos modos, aunque Delphi usa FastMM como valor predeterminado, vale la pena obtener el FastMM completo por su control adicional sobre el registro.


Si obtiene ''Violación de acceso en la dirección 00000000.'', está llamando a un puntero de función que no se ha asignado, posiblemente un controlador de eventos o una función de devolución de llamada.

por ejemplo

type TTest = class(TForm); protected procedure DoCustomEvent; public property OnCustomEvent : TNotifyEvent read FOnCustomEvent write FOnCustomEvent; end; procedure TTest.DoCustomEvent; begin FOnCustomEvent(Self); end;

En lugar de

procedure TTest.DoCustomEvent; begin if Assigned(FOnCustomEvent) then // need to check event handler is assigned! FOnCustomEvent(Self); end;

Si el error está en un componente de un tercero y puede rastrear el código ofensivo hacia abajo, use un controlador de eventos vacío para evitar el AV.


Una infracción de acceso en cualquier lugar cerca de la dirección ''00000000'' indica un acceso nulo al puntero. Está utilizando algo antes de que se haya creado, lo más probable, o después de que haya sido FreeAndNil () ''d.

Muchas veces esto se produce al acceder a un componente en el lugar incorrecto durante la creación del formulario, o al hacer que su forma principal intente y acceder a algo en un módulo de datos que aún no se ha creado.

MadExcept hace que sea bastante fácil hacer un seguimiento de estas cosas, y es gratuito para uso no comercial. (En realidad, una licencia de uso comercial también es bastante económica y vale la pena el dinero).


Use MadExcept. O JclDebug.