c++ debugging 64bit defensive-programming

c++ - ¿Equivale 0xDEADBEEF para el desarrollo de 64 bits?



debugging 64bit (11)

Depende del sistema operativo y del entorno, por supuesto. No creo que 0xDEADBEEF sea necesariamente un mal puntero en un sistema de 32 bits arbitrario, tampoco.

De manera realista, cualquier SO moderno debería proteger sus accesos a las primeras páginas de la memoria de proceso, por lo que NULL debería ser un buen valor de puntero no válido. Convenientemente, ya está predefinido para usted.

Para el desarrollo de C ++ para sistemas de 32 bits (ya sea Linux, Mac OS o Windows, PowerPC o x86), he inicializado punteros que de otro modo no estarían definidos (por ejemplo, no pueden obtener un valor adecuado de inmediato), como por ejemplo:

int *pInt = reinterpret_cast<int *>(0xDEADBEEF);

(Para ahorrar escritura y estar DRY el lado derecho normalmente estaría en una constante, por ejemplo, BAD_PTR).

Si se elimina la referencia de pInt antes de que obtenga un valor adecuado, se bloqueará inmediatamente en la mayoría de los sistemas (en lugar de colapsar mucho más tarde cuando se sobrescribe algo de la memoria o entra en un bucle muy largo).

Por supuesto, el comportamiento depende del hardware subyacente (puede ser perfectamente válido obtener un entero de 4 bytes de la dirección impar 0xDEADBEEF de un proceso de usuario), pero el bloqueo ha sido 100% confiable para todos los sistemas que he desarrollado hasta ahora ( Mac OS 68xxx , Mac OS PowerPC, Linux Redhat Pentium, Windows GUI Pentium, consola de Windows Pentium). Por ejemplo, en PowerPC es ilegal (error de bus) obtener un entero de 4 bytes de una dirección impar.

¿Cuál es un buen valor para esto en sistemas de 64 bits?


Dos 0xDEADBEEF deberían ser suficientes, creo ...


En general, no importa exactamente el patrón que escriba, es importante que pueda identificar el patrón para determinar dónde ocurren los problemas. Da la casualidad de que en el kernel de Linux a menudo se eligen para que puedan quedar atrapados si las direcciones no están referenciadas.

Eche un vistazo en el kernel de Linux en include/linux/poison.h . Este archivo contiene diferentes valores de veneno para muchos subsistemas de kernel diferentes. No hay un valor de veneno que sea apropiado.

Además, puede verificar los archivos de inclusión por arquitectura en el árbol de origen del kernel de Linux para obtener información sobre lo que se utiliza en arquitecturas específicas.


La mayoría de los sistemas actuales de 64 bits le permiten usar solo los 2 48 –2 52 bits más bajos del espacio de direcciones; los bits más altos de la dirección deben ser todos cero. Algunos chips (p. Ej., Amd64) también te permiten usar los más altos 2 48 –2 52 . Las direcciones fuera de estos rangos nunca se pueden asignar a la memoria accesible; el hardware simplemente no lo permitirá.

Por lo tanto, le recomiendo que utilice un valor cercano a 2 63 , que no se encuentra cerca de ninguno de los espacios posiblemente utilizables. Si los cuatro dígitos hexadecimales iniciales son 7ff8, el valor será un NaN de coma flotante de doble precisión, lo cual es conveniente. Así que mi frase hexadecimal linda sugerida es 0x7FF8BADFBADFBADF.

Por cierto, realmente no desea utilizar un valor cercano a 0, porque eso hace que sea difícil diferenciar una diferencia de desplazamiento de NULL (un acceso de miembro de estructura, por ejemplo) de una referencia del patrón de envenenamiento.



Supongo que ya ha descontado NULL (es decir, 0 sin la conversión). Definitivamente, es la opción más segura, ya que, en teoría, un puntero válido podría apuntar a la dirección de memoria 0xDEADBEEF (o cualquier otra dirección de memoria que no sea NULL).


Veo varias respuestas que afirman que NULL es una buena opción, pero no estoy de acuerdo.

NULL se usa a menudo como un valor de retorno válido de las funciones. Indica un retorno de falla o un valor desconocido. Este es un significado diferente al de "puntero sin inicializar".

Usar un depurador en el código y ver NULL dejaría dos posibilidades: el puntero nunca se inicializó o falló una asignación de memoria.

Establecer el puntero no inicializado en 0xDEADBEEF o el equivalente de 64 bits significa que un puntero NULO indica un valor intencional.


De acuerdo con Wikipedia , BADC0FFEE0DDF00D se usa en sistemas IBM RS / 6000 de 64 bits para indicar registros de CPU sin inicializar.


0x42 podría funcionar tanto en 32 bits como en 64 bits? (Aún debería activar un bloqueo, ya que está lo suficientemente cerca del puntero NULL, y dado que es bastante grande, es probable que no lo tenga dentro de una diferencia normal de un campo de estructura con el puntero de la estructura como NULL).


0xBADC0FFEE0DDF00D


0xDEADBEEFBAADF00D podría funcionar.