2011-11-22 12 views
6

Esto es bastante inverosímil, pero es el siguiente código "seguro" (es decir, que no pueda causar fallo de segmentación):¿Es seguro acceder al puntero sin formato después de std :: vector :: reserve?

std::vector<int> vec(1); // Ensures that &vec[0] is valid 
vec.reserve(100); 
memset(&vec[0], 0x123, sizeof(int)*100); // Safe? 

Soy consciente de que esto es feo - Sólo me interesa saber si es técnicamente seguros , no es bonito". Supongo que su único uso podría ser ignorar los valores almacenados más allá de un índice determinado.

Nota! How can I get the address of the buffer allocated by vector::reserve()? cubre el mismo tema, pero estoy más interesado si esto es seguro y si hay trampas para hacer esto.

EDITAR: El código original era incorrecto, reemplazó el original memcpy con memset.

+1

Ok, esto es tan feo que duele. ¿Por qué estás haciendo eso? ¿No puedes simplemente usar una matriz, si realmente tienes que hacerlo? En este ejemplo, 100 es fijo, por lo que podría usar una matriz en la pila sin eliminar [] ing ... – Francesco

+2

"Error de segmentación" es un evento específico de la plataforma. El lenguaje C++ no describe de qué se trata. El idioma solo dice si algo está definido, y si es así, para hacer qué. –

+1

He votado negativamente, no porque lo considere una mala pregunta, sino porque no se tomó el tiempo suficiente para asegurarse de que lo que estaba preguntando era lo que quería decir (el código original y el código en la versión actual son bastante diferente).-2 puntos de repetición no son muchos, pero deberían recordarle en el futuro que sea un poco más cuidadoso, como cuando le pide a otras personas que se tomen el tiempo para responder tratando de ayudar, y ese es el momento que se desperdicia si reformula la pregunta más adelante en. –

Respuesta

16

No, no es seguro.

Después de reserve(), se garantiza que el vector no reasignará el almacenamiento hasta que se alcance el capacity().

Sin embargo, la norma no indica qué puede hacer la implementación del vector con el almacenamiento entre size() y capacity(). Tal vez se pueda usar para algunos datos internos, ¿quién sabe? ¿Tal vez el espacio de direcciones está reservado y no está asignado a la RAM real?

El acceso a elementos fuera de [0..size] es un comportamiento indefinido. Hay podría ser algo de verificación de hardware para eso.

+0

upped para señalar _why_ esta es una mala idea: la memoria reservada es UB y no está disponible 'oficialmente' a través del vector hasta que haya sido 'resize'd o' push'/'emplace'd to. –

2

Vector-reasignación invalida punteros, referencias, etc. Reserva existentes podría desencadenar una reasignación (23.3.6.2, [vector.capacity]), pero usted está tomando la dirección del primer elemento después de la eventual reasignación (que en este caso probablemente no ocurra en absoluto, pero eso es además del punto). Entonces no veo ningún problema con el código.

+0

Actualicé mi pregunta para usar memset en lugar de 'memcpy (mi ejemplo era incorrecto). – larsmoa

2

Primero tenga en cuenta que su memset truncará el 0x123 en un solo byte y escribirá eso, sin escribir un patrón de cuatro bytes.

Entonces, no hagas eso, sólo tiene que utilizar el contenedor: std::vector<int> vec(100, whatever_value_you_want);

Sin embargo, para responder a la pregunta que pueda parecer a trabajar específicamente para este tipo de POD si el compilador no utiliza el espacio asignado para nada. Ciertamente, si alguien llama al resize, insert, push_back etc., destruirá todo lo que ya ha escrito en la memoria y el tamaño del vector también será incorrecto. Simplemente no hay razón para escribir dicho código.

Cuestiones relacionadas