es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Aporta seguridad acceder a uintptr_t al realizar la conversión de un tipo de puntero a uint64_t?

Tenga en cuenta que esta es puramente una pregunta académica, desde una perspectiva legal del lenguaje. Se trata de la forma teóricamente más segura de lograr la conversión.

Supongamos que tengo un ‘void*’ y necesito convertirlo a un entero de 64 bits. La razón es que este puntero contiene la dirección de una instrucción que genera un error; deseo informarlo a mi backend para que se registre, y uso un protocolo de tamaño fijo, por lo que tengo exactamente 64 bits para usar para la dirección.

El tipo de conversión será, por supuesto, definido por la implementación. Sé que mi plataforma (Windows de 64 bits) permite esta conversión, por lo que en la práctica está bien simplemente realizar un ‘reinterpret_cast(address)’.

Pero me pregunto: desde un punto de vista teórico, ¿es más seguro convertir primero a ‘uintptr_t’? Es decir: ‘static_cast(reinterpret_cast(address))’. https://en.cppreference.com/w/cpp/language/reinterpret_cast dice (énfasis mío):

“Al contrario que ‘static_cast’, pero similar a ‘const_cast’, la expresión ‘reinterpret_cast’ no se compila en ninguna instrucción del CPU (excepto al convertir entre enteros y punteros o en arquitecturas oscuras donde la representación del puntero depende de su tipo)”.

Entonces, en teoría, la representación del puntero no está definida como algo en particular; al convertir de puntero a ‘uintptr_t’, teóricamente se podría realizar una conversión de algún tipo para hacer que el puntero sea representable como un entero. Después de eso, extraigo de forma forzada los 64 bits inferiores. Mientras que simplemente hacer la conversión directa a ‘uint64_t’ no desencadenaría la conversión mencionada anteriormente, por lo que obtendría un resultado diferente.

¿Es correcta mi interpretación, o no hay diferencia alguna entre los dos ‘casts’ en teoría también?

Por cierto, en un sistema de 32 bits, al parecer, la conversión de ampliación a un 64 bits sin signo podría extender el signo, como en este caso. Pero en un sistema de 64 bits, no debería tener ese problema.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Teóricamente, puede haber una diferencia entre convertir directamente un void* a uint64_t y primero convertirlo a uintptr_t y luego hacer la conversión a uint64_t. Esto se debe a que el estándar de C++ no define la representación de un puntero como un entero. Por lo tanto, convertir un puntero a un tipo entero puede realizar alguna conversión para hacer que el puntero sea representable como un entero. Sin embargo, esto solo debería suceder en arquitecturas oscuras donde la representación del puntero depende de su tipo.

    En la práctica, en una plataforma de 64 bits como Windows, ambas conversiones deberían dar como resultado el mismo valor y no debería haber diferencia entre ellas. También cabe destacar que la conversión de ampliación a un entero sin signo de 64 bits podría extender el signo en un sistema de 32 bits, pero esto no debería ser un problema en un sistema de 64 bits.

Comments are closed.