2011-12-04 13 views
5

Si es legal tomar la dirección más allá del final de una matriz, ¿cómo haré esto si el último elemento de la dirección de la matriz es 0xFFFFFFFF?¿Cómo tomo la dirección de uno pasado el final de una matriz si la última dirección es 0xFFFFFFFF?

¿Cómo sería el código de trabajo:

for (vector<char>::iterator it = vector_.begin(), it != vector_.end(); ++it) 
{ 
} 

Editar:

leí aquí que es legal antes de hacer esta pregunta: May I take the address of the one-past-the-end element of an array?

+0

¿Qué te hace pensar que '0xFFFFFFFF' es el elemento más grande posible? ¿Qué pasa con las arquitecturas de 64 bits? –

+3

Es * no * legal acceder a punteros uno-pasado-al-fin. Solo es legal crearlos, no desreferenciarlos. – Xeo

+0

@Chris Eso es lo que quería saber, si estoy haciendo suposiciones no válidas que posiblemente pueda aclarar. Y digamos solo 32 bits. – Marlon

Respuesta

9

Si esta situación es un problema para una arquitectura en particular (puede o no), entonces se puede esperar que el compilador y el tiempo de ejecución arreglen que las matrices asignadas nunca terminen en 0xFFFFFFFF. Si no lo hicieran, y algo se rompe cuando termina un array , entonces no cumplirían con el estándar C++.

+0

En arquitecturas "normales" esto ni siquiera será un problema, creo, porque la pila está por encima del montón, donde 'vector' almacena sus contenidos. –

+0

@GregHewgill ¡Gracias, esto es lo que pensé y ustedes respondieron mi pregunta! – Marlon

1
  • Es no legal para acceso una pasada el final de una matriz
  • ese código no realmente tiene acceso a esa dirección.
  • y nunca obtendrá una dirección como esa en un sistema real para sus objetos.
+3

Creo que la pregunta tiene más que ver con el desbordamiento de un número entero que con el acceso ilegal a la memoria. –

+0

Si el puntero desbordando a 0 era legal, la implementación tendría que hacer gimnasia loca para asegurarse de que 'ptr_one_past_end> ptr_start'. –

+0

@R. Martinho Fernandes: correcto ... quítalo. –

3

El acceso fuera de los límites de la matriz es un comportamiento indefinido. No debería sorprenderse si un demonio se sale de su nariz (o algo así)

Lo que en realidad podría pasar sería un desbordamiento en la dirección que podría llevarlo a leer la dirección cero y, por lo tanto, la falla de segmentación.

Si siempre está dentro del rango de matriz, y hace el último ++it que sale del conjunto y lo compara con _vector.end(), entonces no está realmente accediendo a nada y no debería haber ningún problema.

+0

La norma garantiza que es legal obtener un puntero a un elemento más allá del final de la matriz (por supuesto, * no * es legal desreferenciarlo). –

+0

@MatteoItalia por lo tanto el "_entonces no está realmente accediendo a nada y no debería haber un problema." "Pero gracias por estresar eso – Shahbaz

+0

Correcto, lo estaba estresando nuevamente solo porque la primera oración parecía dar una idea equivocada sobre eso. –

0

La diferencia es entre desreferenciar ese elemento y tomar su dirección. En su ejemplo, el elemento más allá del final no será desreferenciado, por lo que es válido. Aunque esto no era muy claro en los primeros días de C++, ahora está claro. Además, el valor que pasas al subíndice en realidad no importa.

1

Creo que hay un buen argumento para sugerir que una implementación conforme a C no puede permitir que una matriz termine en (por ejemplo) 0xFFFFFFFF.

Let p ser un puntero a un elemento-de-la-end-of-the-matriz: si buffer está declarada como char buffer[BUFFSIZE], entonces p = buffer+BUFFSIZE, o p = &buffer[BUFFSIZE]. (Esto último significa lo mismo, y su validez se explicitó en el documento estándar C99.)

Esperamos entonces que las reglas ordinarias de comparación de punteros funcionen, ya que la inicialización de p fue un bit ordinario de aritmética de puntero. (No puede comparar punteros arbitrarios en C estándar, pero puede compararlos si ambos están basados ​​en una única matriz, búfer de memoria o estructura). Pero si buffer terminara en 0xFFFFFFFF, entonces p sería 0x00000000, y tendríamos el situación improbable que p < buffer!

Esto rompería una gran cantidad de código existente que asume que, en la aritmética válida del puntero hecha en relación con una base de matriz, se cumple la propiedad intuitiva de ordenamiento de direcciones.

+2

Una implementación de C conforme podría usar una representación de puntero interno que no se asigna directamente a las direcciones de memoria. Por ejemplo, podría decidir que la dirección de memoria 'N' esté representada por el valor del puntero' N-1'. Tal implementación gana la capacidad de acceder al byte 0xFFFFFFFF al sacrificar la capacidad de acceder a los bytes 1. Win32s funcionaba de esta forma (excepto que el sesgo no era 1 sino más bien alrededor de 4MB). –

0

A veces, lo mejor que puede hacer con los casos de esquina es prohibirlos. Vi esta clase de problema con algunas instrucciones de extracción de campo de bit del NS32032 en las que el hardware cargaría 32 bits comenzando en la dirección de bytes y extrayendo de ese dato. Así que incluso los campos de un solo bit en cualquier lugar en los últimos 3 bytes de memoria mapeada fallarían. La solución fue nunca permitir que los últimos 4 bytes de memoria estuvieran disponibles para la asignación.

0

Bastantes arquitecturas que se verían afectadas por esto resuelven el problema al reservar el offset 0xFFFFFFFF (y un poco más) para el sistema operativo.

Cuestiones relacionadas