Cuando se programa a veces las cosas se rompen. Cometiste un error y tu programa intenta leer desde una dirección incorrecta.
Una cosa que me llama la atención es que a menudo esas excepciones son:
Access violation at address 012D37BC in module 'myprog.exe'. Read of address 0000000C.
Ahora veo muchos registros de errores y lo que más me llama la atención es: 0000000C. ¿Es esta una dirección "especial"? Veo otras violaciones de acceso con malas lecturas, pero las direcciones parecen aleatorias, pero esta sigue volviendo en situaciones totalmente diferentes.
windows
error-handling
error-messages
Pieter B
fuente
fuente
0000000C
es mucho más común que eso00000008
, pero ninguna de las respuestas parece abordar eso en absoluto: /System.Runtime.CompilerServices.RuntimeHelpers.OffsetToStringData
sea la12=0x0C
razón por la cual este desplazamiento es más común.Respuestas:
00000000
es una dirección especial (el puntero nulo).0000000C
es justo lo que obtienes cuando agregas un desplazamiento de 12 al puntero nulo, muy probablemente porque alguien intentó obtener elz
miembro de una estructura como la siguiente a través de un puntero que en realidad era nulo.fuente
En Windows es ilegal eliminar referencia a la totalidad de primera y la última página , en otras palabras, la primera o la última 64 KiB de la memoria del proceso (los intervalos
0x00000000
a0x0000ffff
y0xffff0000
a0xffffffff
en una aplicación de 32 bits).Esto es para atrapar el comportamiento indefinido de desreferenciar un puntero o índice nulo en una matriz nula. Y el tamaño de la página es de 64 KiB, por lo que Windows solo tiene que evitar que la primera o la última página tengan asignado un rango válido.
Esto no protegerá contra punteros no inicializados que podrían tener algún valor (incluidas las direcciones válidas).
fuente
En cuanto a por qué
0x0C
parece más común que0x08
(¿es realmente? No lo sé; y ¿en qué tipo de aplicaciones?), Esto podría tener que ver con punteros de tabla de métodos virtuales. Esto es realmente más un comentario (adivinanzas masivas :), pero es algo más grande, así que aquí va ... Si tienes una clase con métodos virtuales, sus propios campos se cambiarán0x04
. Por ejemplo, una clase que hereda de otra clase virtual podría tener un diseño de memoria como este:¿Es este un escenario común, o incluso cercano? No estoy seguro. Sin embargo, tenga en cuenta que en una aplicación de 64 bits, esto podría cambiar aún más interesantemente hacia el
0x0C
valor:Entonces, en realidad, hay muchos casos en los que las aplicaciones pueden tener una superposición significativa en las compensaciones de puntero nulo. Puede ser el primer campo en una clase secundaria, o su puntero de tabla de método virtual, necesario siempre que llame a cualquier método virtual en una instancia, por lo que si llama a un método virtual en un
null
puntero, obtendrá una infracción de acceso en su VMT offset. La prevalencia de este valor particular podría tener algo que ver con alguna API común que proporciona una clase que tiene un patrón de herencia similar, o más probablemente, una interfaz particular (bastante posible para algunas clases de aplicaciones, como los juegos de DirectX). Es posible rastrear alguna causa común simple como esta, pero tiendo a deshacerme de las aplicaciones que anulan la referencia nula con bastante rapidez, así que ...fuente