Reputation: 4399
I have been using a std::vector to store some binary data read from a file, which is then serialized into a data gram sent over a socket. I wrote the unittest for the end-to-end functionality but it failed for unexpected reasons:
std::vector<char> buf;
response->data(buf);
ASSERT(1 == buf.size());
The idea was to transfer 1 byte and receive 1 byte. What I actually got was 4 bytes.
Essentially what happened was that the insert event used in both encoding and decoding, resized the vector to bufsize * 2 bytes or chars. I didn't see this in the documentation anywhere.
unsigned long sourceLen = 1;
char source[] = { '0' };
...
std::vector<char> buf;
buf.resize(sourceLen);
buf.insert(buf.begin(), source, source + sourceLen);
ASSERT(1 == buf.size()); // Fails: buf.size() == 2.
This happens again at the receiving end in the decode method and results in a buffer of four bytes. I solved the issue by not using the insert method and instead implementing a C style loop:
buf.resize(sourceLen);
for (unsigned long i = 0; i < sourceLen; ++)
{
buf[i] = source[i];
}
ASSERT(1 == buf.size()); // Succeeds: buf.size() == 1.
So why does insert resize the vector in such a way that you end up with more data than you started with? Oh, I did try this, which solved the buffer size issue, but resulted in no data being copied:
buf.resize(sourceLen);
buf.insert(buf.begin(), data, data + dataLen - 1);
ASSERT(1 == buf.size()); // Succeeds: buf.size() == 1.
ASSERT(buf[0] == source[0]); // Fails: buf[0] == ''.
As always is the case, I had a thought after I submitted the question. Is it the case that the insert is retaining the current contents and inserting the new values? I.e. The resize of the vector should resize it to zero bytes before calling insert?
Update:
I missed this in the documentation...
The vector is extended by inserting new elements before the element at the specified position, effectively increasing the container size by the number of elements inserted.
Upvotes: 0
Views: 211
Reputation: 1369
std::insert()
inserts the new values and relocates the old values. The behaviour you described is thus to be expected. You should use std::copy()
instead.
Upvotes: 1