2009-03-11 18 views
14

Necesito manipular los datos en una matriz fija que implica una inserción intermedia. En lugar de usar memcpy, etc. Quiero usar el vector. Tengo un problema cuando quiero para copiar los elementos vectoriales a la matriz c-style. Aquí está el código:¿Cómo copiar los contenidos de std :: vector a array estático c-style, de forma segura?

void tryvector() 
{ 
    using namespace std; 
    const int MAX_SIZE=16; 
    BYTE myarr[MAX_SIZE]={0xb0,0x45,0x47,0xba,0x11,0x12, 0x4e}; 
    vector<BYTE> myvec (myarr, myarr+MAX_SIZE); 
    vector<BYTE>::iterator it; 

    printf("myarr pre :"); 
    for(int i=0;i<MAX_SIZE;++i){ 
     printf("%02x ", myarr[i]) ; 

    } 

    printf("\nmyvec pre :") 
    for(it=myvec.begin(); it<myvec.end();++it){ 
     cout<<hex<<static_cast<int>(*it)<<" "; 

    } 

    it = myvec.begin()+ 3; 
    myvec.insert(it,0x5f); 
    printf("\nmyvec post:"); 
    for(it=myvec.begin(); it<myvec.end();++it){ 
     cout<<hex<<static_cast<int>(*it)<<" "; 


    } 

    copy(myvec.begin(), myvec.end(), myarr); //??? 
    printf("\nmyarr post:"); 
    for(int i=0;i<MAX_SIZE;++i){ 
     printf("%02x ", myarr[i]) ; 

    } 

} 

estoy usando vs 2005. aquí está la advertencia:

warning C4996: 'std::_Copy_opt' was declared deprecated 
1>  c:\program files\microsoft visual studio 8\vc\include\xutility(2270) : see  declaration of 'std::_Copy_opt' 
1>  Message: 'You have used a std:: construct that is not safe. See documentation on how to use the Safe Standard C++ Library' 
1>  c:\documents and settings\mhd\my documents\tesvector.cpp(50) : see reference to function template instantiation '_OutIt std::copy<std::_Vector_iterator<_Ty,_Alloc>,BYTE*>(_InIt,_InIt,_OutIt)' being compiled 
1>  with 
1>  [ 
1>   _OutIt=BYTE *, 
1>   _Ty=BYTE, 
1>   _Alloc=std::allocator<BYTE>, 
1>   _InIt=std::_Vector_iterator<BYTE,std::allocator<BYTE>> 
1>  ] 

Cuando lo ejecuto, me dieron el error de tiempo de ejecución:


    Run-Time Check Failure #2 - Stack around the variable 'myarr' was corrupted. 

Tenga en cuenta que utilizo el vector en su lugar list o deque porque la 'inserción del medio' como el código anterior es juat un problema particular Lem. Pasará menos que 'insertando al final' y 'acceso aleatorio del elemento'.
¿Alguna solución?

Cualquier respuesta que se asemeje a: "Utiliza C++, suelta la implementación de la matriz de estilo c. Usar solo el vector para toda la implementación de la matriz" no es realmente útil.

Gracias.

+0

El hecho de que esté utilizando vector <> en lugar de una matriz no significa que memcpy() no esté sucediendo. Los métodos vectoriales <> son más fáciles de entender, pero hacen lo mismo y el rendimiento será pobre para arreglos grandes. – slacy

Respuesta

18

El problema es que está agregando elementos al vector, por lo que termina con más elementos que en la matriz myarr con la que lo inicializó.

Si desea copiar el vector de nuevo en la matriz, tendrá a su tamaño abajo:

myvec.resize(MAX_SIZE); 

O bien, podría limitar el número de elementos de copiar de vuelta:

copy(myvec.begin(), myvec.begin()+MAX_SIZE, myarr); 

Si desea que la matriz myarr contenga todos los elementos, debe ser mayor que MAX_SIZE, y ha descubierto por qué las personas sugieren usar vector en lugar de matrices en bruto (vector s saben cómo crecer, las matrices no) .

Tenga en cuenta que si bien no desea 'Cualquier respuesta que se asemeje a: "Utiliza C++, suelte la implementación del conjunto de estilos c. Use solo el vector para toda la implementación de matriz' ', a menudo puede usar vector y pasando &myvec[0] a rutinas que esperan una matriz sin procesar. vector es necesario para almacenar sus elementos de forma contigua al igual que una matriz sin procesar por este motivo.

Como aparece la advertencia 'operación insegura', está utilizando el compilador de Microsoft. Para solucionar el problema de forma segura, se supone que debe utilizar el algoritmo checked_copy en lugar de copy. Como Evgeny Lazin indicates, puede crear un iterador marcado para que su matriz pase al algoritmo checked_copy.

Otras opciones para hacer la copia segura que no requieren extensiones de Microsoft serían envolver la matriz en una clase (posiblemente con plantilla) que realiza un seguimiento del tamaño de la matriz y proporciona métodos para copiar datos en la matriz de forma segura . Algo como STLSoft's array_proxy template o Boost's boost::array podría ayudar.

+0

Sí, esto resuelve el problema de tiempo de ejecución. –

+0

Esto parece funcionar, pero la advertencia todavía está allí. ¿Está bien? – mhd

+0

tenga en cuenta que ahora con C++ 11 también hay std :: array –

0

Usted puede hacer:

memcpy(myarr, &(myvec)[0], myvec.size()) 

Editar: En lo que va de seguridad, de acuerdo con this, almacenar datos de vectores en segmentos contiguos de memoria, de modo que puedan acceder a ellos "no sólo el uso de iteradores, sino también el uso de compensaciones en punteros regulares a los elementos ".

+0

Esto tendrá el mismo problema ya que myvec.size() es más grande que myarr. Tiene el problema adicional de no funcionar como se esperaba si cambia el tipo del vector y la matriz. –

+0

Sí, solo soluciona el problema de tiempo de compilación. –

+0

También tenga en cuenta que no es seguro tomar la dirección de [0] de un vector si está vacío. Los tiempos de ejecución más recientes de VC++ se quejarán ruidosamente de esto (y con razón, en mi humilde opinión). –

3

En general, supongo que se podría hacer algo como esto:

void *myarr; 

if((myarr = malloc(myvec.size() * sizeof myvec[0])) != NULL) 
{ 
    memcpy(myarr, &myvec[0], myvec.size() * sizeof myvec[0]); 
    /* Do stuff with the C-style array for a while 
    . 
    . 
    . 
    */ 
    free(myarr); /* Don't forget handing back the memory when done. */ 
} 

Esto asigna una nueva matriz de estilo C para mantener los elementos del vector, y copia los datos en su lugar. De esta forma, no es necesario igualar los tamaños de forma estática.

Por supuesto, esto es general, por lo que solo te da void * para acceder a tu matriz C, por lo que necesitas echar o simplemente cambiar el tipo al tipo real (BYTE en este caso).

+0

¿Escribes código de esta manera regularmente como este? –

+0

Debe usar new/delete [] en lugar de malloc/free en C++ – codymanix

1

Puede usar la plantilla deducción argumento para encontrar la matriz obligado:

template<typename T, size_t N> 
size_t copy(std::vector<T> const& src, T[N] dest) { 
    size_t count = std::min(N, src.size()); 
    std::copy(src.begin(), src.begin()+count, dest); 
    return count; 
} 

Apague las advertencias de Microsoft acerca de cosas sin marcar. Están destinados a engañarte para que escribas un código poco práctico.

+2

+1 para la técnica. ¿Pero "atrayéndolo a escribir un código que no es portátil"? MS proporciona una implementación conforme, aumentada con características de seguridad opcionales que son fáciles de apagar, y las personas * se quejarán * al respecto, increíble. –

+0

Consulte la referencia a "Biblioteca estándar segura de C++" en la advertencia, que NO es un estándar. La idea detrás de esto no es tan mala, pero deberían haber sido consistentes en el nombramiento. P.ej. stdext :: checked_iterator/es/named. – MSalters

Cuestiones relacionadas