How to copy the contents of std::vector to c-style static array,safely?

28,292

Solution 1

The problem is that you're adding things to the vector so it ends up with more elements than were in the myarr array that you initialized it with.

If you want to copy the vector back into the array, you'll need to size it down:

myvec.resize( MAX_SIZE);

Or you could limit the number of elements you copy back:

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

If you want the myarr array to contain all the elements, then it needs to be larger than MAX_SIZE, and you've found out why people suggest to use vector rather than raw arrays (vectors know how to grow, arrays do not).

Note that while you don't want 'Any answer that resembles:"You use c++, drop the c style array implementation. Use only vector for all array implementation"', you can often get away with using a vector and passing &myvec[0] to routines that expect a raw array. vector is required to store its elements contiguously just like a raw array for just this reason.

Since you're getting the 'unsafe operation' warning, you're using Microsoft's compiler. To fix the problem safely, you're supposed to use the checked_copy algorithm instead of copy. As Evgeny Lazin indicates, you can create a checked iterator for your array to pass to the checked_copy algorithm.

Other options to make the copy safe that do not require Microsoft extensions would be to wrap the array in a class (possibly templated) that keeps track of the array size and provides methods to copy data into the array in a safe manner. Something like STLSoft's array_proxy template or Boost's boost::array might help.

Solution 2

In general, I guess you could do something like this:

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. */
}

This allocates a new C-style array to hold the vector's elements, and copies the data in place. This way the there is no need to match the sizes statically.

Of course, this is general so it just gives you a void * to access your C array with, so you need to either cast or just change the type to the actual type (BYTE in this case).

Solution 3

You can use template argument deduction to find the array bound:

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;
 }

Turn off the Microsoft warnings about unchecked stuff. They're aimed at luring you into writing unportable code.

Share:
28,292
mhd
Author by

mhd

Updated on July 09, 2022

Comments

  • mhd
    mhd almost 2 years

    I need to manipulate data in fixed array involving mid insertion. Rather than using memcpy,etc. I want to use vector. I have problem when I want to copy the vector elements back to the c-style array. Here's the code:

    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]) ;   
    
        }
    
    }
    

    I'm using vs 2005. Here's the warning:

    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>        ]
    

    When I run it , I got the following run-time error:

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

    Please note that I use vector instead list or deque because the 'middle insertion' like the code above is juat a particular problem. It will happen less than 'inserting at the end' and 'random access of element'.
    Any solution ?

    Any answer that resembles:"You use c++, drop the c style array implementation. Use only vector for all array implementation" is not really helpful.

    Thanks.