Reputation:
I copied the struct into a vector and put it back into the struct. Why did this bug occur? use std::copy
incorrectly?
When copying, I used std::copy
, and I copied structures one by one.
This is the code:
struct test_msg
{
int32_t msg_type =0;
int32_t msg_id =0;
int32_t src = 0 ;
int32_t dst = 0;
std::string data;
bool Serialize(std::vector<char> &out) {
out.clear();
std::copy(&msg_type, &msg_type + sizeof(msg_type), std::back_inserter(out));
std::copy(&msg_id,&msg_id + sizeof(msg_id), std::back_inserter(out));
std::copy(&src,&src + sizeof(src), std::back_inserter(out));
std::copy(&dst,&dst + sizeof(dst), std::back_inserter(out));
std::copy(json_string.begin(),json_string.end(), std::back_inserter(out));
return true;
};
bool Deserialize(std::vector<char> &out) {
int last_index = 0;
std::copy(out.begin() + last_index, out.begin() +last_index + sizeof(msg_type), &msg_type); last_index += sizeof(msg_type);
std::copy(out.begin() + last_index, out.begin() +last_index + sizeof(msg_id), &msg_id); last_index += sizeof(msg_id);
std::copy(out.begin() + last_index, out.begin() +last_index + sizeof(src), &src); last_index += sizeof(src);
std::copy(out.begin() + last_index, out.begin() +last_index + sizeof(dst), &dst); last_index += sizeof(dst);
// std::copy(out.begin() + last_index, out.begin() +last_index + sizeof(synchronous), &synchronous); last_index += sizeof(synchronous);
std::copy(out.begin() + last_index, out.end(), std::back_inserter(json_string));
return true;
};
};
int main(int argc, char *argv[]) {
testmsg msg;
msg.msg_type =11;
msg.msg_id =22;
msg.src =33;
msg.dst =44;
msg.json_string = "this is test!this is test!this is test!\0";
std::vector<char> data;
msg.Serialize(data);
IpcJsonMessage msg2;
msg2.Deserialize(data);
return 1;
}
Upvotes: 0
Views: 67
Reputation: 2573
The issue is that you're using std::copy
to copy int32s
which will iterate int32s but you're thinking it will iterate bytes:
std::copy(&msg_type, &msg_type + sizeof(msg_type), std::back_inserter(out));
In this case you will most likely be copying 4 non-contiguous bytes - from offsets 0, 4, 8, 12 (LSB first), since the iteration will work in the same fashion as when you're incrementing C pointers (i.e. int32* pX; pX++;
will increment pX by one int32 -> 4 bytes). Each iteration will load an int32 from memory but only add the least significant byte to the char vector.
It helps to think of how the std::copy unrolls:
int32* pIter;
int32* pEnd; //pIter+4 i.e 16 bytes ahead of pIter
vector<char> dest;
while (pIter < pEnd)
{
int32 value = *pIter;
dest.push_back (value); //loses the upper 24 bits of value
pIter++;
}
See here for a full explanation: Copy Memory to std::copy
Here is a screendump from running a snippet in Visual Studio:
In terms of a solution to the problem, take a look at: Is it possible to serialize and deserialize a class in C++?
Upvotes: 3