2012-02-12 16 views
5

En C++ cuando lo hago new (o incluso malloc) ¿hay alguna garantía de que la dirección de devolución será mayor que un cierto valor? Porque ... en este proyecto lo encuentro muy útil para usar 0-1k como una enumeración. Pero no me gustaría hacer eso si es posible obtener un valor tan bajo. Mis únicos sistemas de destino son las CPU de 32 o 64 bits con la ventana OS/linux y mac.¿Está garantizado que el puntero sea> cierto valor?

¿El estándar dice algo acerca de los punteros? ¿Windows o Linux dicen algo sobre su tiempo de ejecución C y cuál es la dirección de memoria más baja (para RAM)?

-editar- termino modificando mi sobrecarga new para verificar si la dirección es superior a 1k. Llamo a std :: terminate si no es así.

+1

¿Por qué usa enums como punteros? – Pubby

+1

@Pubby: es común (particularmente en intérpretes y juegos) confiar en las características del puntero específicas de la plataforma para incluir información adicional en ellas, generalmente para eliminar la indirección.Debido a las reglas de alineación, los tres bits inferiores son gratuitos; además, los sistemas de 64 bits generalmente tienen punteros de espacio de usuario con solo 48 bits significativos; el resto son todos '1' o' 0', por lo que puede empaquetar un puntero en la mantisa (53 bits) de un 'doble' con sus bits superiores establecidos para representar' NaN'. Luego, las banderas de orden bajo le permiten elegir rápidamente entre representaciones con enmascaramiento y desplazamiento. –

+0

Parece que solo necesito 6 bits, así que ni siquiera necesitaré los primeros 1 o 4k :). –

Respuesta

4

No hay tal garantía. Puede intentar usar placement new si necesita ubicaciones de memoria muy específicas, pero tiene ciertos problemas que tendrá que work hard to avoid. ¿Por qué no intentas usar un mapa con una clave entera que tenga el puntero como su valor? De esta forma no tendrías que depender de direcciones de memoria y rangos específicos.

2

En teoría, no, ni siquiera se garantiza que un puntero sea> 0. Sin embargo, en la práctica, se ve como un entero sin signo (no olvide que un puntero puede tener un bit "1" de orden alto), ningún sistema que yo conozca tendría un valor de puntero inferior a aproximadamente 1000. Pero confiar en eso depende de un "comportamiento indefinido".

+1

referencia? Creo que recuerdo haber leído que el primer 1GB en la memoria virtual de Linux es solo para el kernel, [así que si es verdad, tu aplicación no obtendrá una dirección en el primer 1GB, a menos que se ejecute en modo kernel] Sin embargo, podría ser mal sobre la suposición inicial, no puedo recordar dónde creo que lo leí: \ – amit

+0

@amit mi google-fu inventó este http://linux-mm.org/HighMemory "3GB para programas de usuario y 1GB para kernel" –

+0

@amit - Hablaba muy en general - C++ se ejecuta en algunos sistemas bastante pequeños. –

1

No existe un estándar para el origen de direcciones válidas de memoria; para escribir código seguro independiente del sistema, no puede confiar en ciertas direcciones (e incluso con soporte anecdótico, nunca se sabe cuándo cambiará eso con una nueva actualización del sistema).

6

En términos de estándar, no hay nada. Pero en realidad, depende del sistema operativo objetivo, Windows por ejemplo reserva los primeros 64 kb de memoria como tierra de nadie (dependiendo de la construcción, es memoria de solo lectura, de lo contrario, está marcada como PAGE_NOACCESS), mientras usa el superior 0x80000000 + para la memoria del kernel, pero se puede cambiar, consulte this & this en MSDN.

En x64 también puede usar los bits más altos de la dirección (solo 47bits se usan para las direcciones actualmente), pero no es una buena idea, ya que más tarde cambiará y su programa se romperá (AMD que configuró el el estándar también desaconseja).

+0

buena respuesta +1. –

1

Es muy específico de la plataforma, por lo que desanimaría a depender de este tipo de información a menos que tenga una muy buena razón y son conscientes de las consecuencias para la portabilidad, facilidad de mantenimiento, etc.

NULL se garantiza que sea 0x0 siempre. Si recuerdo correctamente, x86 reserva los primeros 128 MB de espacio de direcciones como "NULO-equivalente", por lo que los punteros válidos no pueden tomar valores en este rango. En x64 hay algunos additional addresses que no deberían encontrarse en la práctica, al menos por ahora.

En cuanto al espacio de direcciones reservado para el sistema operativo, claramente dependerá del sistema operativo. En Linux, la división del espacio kernel-user es configurable en el kernel, por lo que al menos las 3 divisiones: 1-3 GB, 2-2 GB y 3-1 GB son comunes en los sistemas de 32 bits. Puede encontrar más detalles on kerneltrap.

+0

Seguramente se refería a los primeros 128 * K * B del espacio de direcciones? –

+0

@CodyGray No, en realidad es 128 MB, no kB. Pero no tenía razón sobre las causas. No es causado por la propia CPU sino más bien por el diseño del espacio de direcciones de las aplicaciones en la mayoría de los sistemas tipo UNIX. El área 0-128 MB está reservada para la pila, lo que significa que no se obtienen direcciones de este rango cuando se usa 'new' o' malloc() 'que asignan memoria desde el montón. Se explica muy bien en [esta buena respuesta] (http://stackoverflow.com/a/2187753/1224016). –

Cuestiones relacionadas