std::copy wrong value issue!!!!!!

I copied the struct into a vector and put it back into the struct. Why did this bug occur? use std::copy incorrectly?

[code]

struct test_msg
{
public:
int32_t msg_type =0;
int32_t msg_id =0;
int32_t src = 0 ;
int32_t dst = 0;

std::string data;

test_msg() : msg_type(0), msg_id(0), src(0), dst(0), json_string("") {
;
};
virtual ~test_msg() {
;
};
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.end(), std::back_inserter(json_string));

return true;
};
};


int main(int argc, char *argv[]) {

test_msg 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);

printf ("result : %d %d %d %d [%s]\n", msg.msg_type, msg.msg_id, msg.src, msg.dst, msg.json_string.c_str());
IpcJsonMessage msg2;
printf ("result : %d %d %d %d [%s]\n", msg2.msg_type, msg2.msg_id, msg2.src, msg2.dst, msg2.json_string.c_str());
msg2.Deserialize(data);
printf ("result : %d %d %d %d [%s]\n", msg2.msg_type, msg2.msg_id, msg2.src, msg2.dst, msg2.json_string.c_str());

return 1;
}

result ====>
result : 11 22 33 44 [this is test!this is test!this is test!] │
result : 0 0 0 0 [] │
deserial 4 4 4 4 │
Segmentation fault (core dumped)
Show your whole, runnable code (ideally as a single file).

Your struct seems to have a data member called data.
You seem to be playing around with something called json_string.


struct test_msg
{
public:
int32_t msg_type =0;
int32_t msg_id =0;
int32_t src = 0 ;
int32_t dst = 0;

std::string data;

test_msg() : msg_type(0), msg_id(0), src(0), dst(0), json_string("") {
;
};
The problem is the type mismatch in your copy.

An expression like this:

std::copy(out.begin() + last_index, out.begin() +last_index + sizeof(dst), &dst);

will basically do this (assuming sizeof(dst)==4):

(&dst)[0] = out[last_index];
(&dst)[1] = out[last_index + 1];
(&dst)[2] = out[last_index + 2];
(&dst)[3] = out[last_index + 3];

Which will override following data member (json_string).
What you need to do is something like reinterpret_cast<char *>(&dst)
The same issue also arises in Serialize. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <algorithm>
#include <iostream>
#include <vector>

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((char*)&msg_type, (char*)&msg_type + sizeof(msg_type), std::back_inserter(out));
		std::copy((char*)&msg_id, (char*)&msg_id + sizeof(msg_id), std::back_inserter(out));
		std::copy((char*)&src, (char*)&src + sizeof(src), std::back_inserter(out));
		std::copy((char*)&dst, (char*)&dst + sizeof(dst), std::back_inserter(out));
		std::copy(data.begin(), data.end(), std::back_inserter(out));

		return true;
	}

	bool Deserialize(const std::vector<char>& out) {
		int last_index = 0;

		data.clear();

		std::copy(out.begin() + last_index, out.begin() + last_index + sizeof(msg_type), (char*)&msg_type); last_index += sizeof(msg_type);
		std::copy(out.begin() + last_index, out.begin() + last_index + sizeof(msg_id), (char*)&msg_id); last_index += sizeof(msg_id);
		std::copy(out.begin() + last_index, out.begin() + last_index + sizeof(src), (char*)&src); last_index += sizeof(src);
		std::copy(out.begin() + last_index, out.begin() + last_index + sizeof(dst), (char*)&dst); last_index += sizeof(dst);
		std::copy(out.begin() + last_index, out.end(), std::back_inserter(data));

		return true;
	}
};


int main(int argc, char* argv[]) {

	test_msg msg;

	msg.msg_type = 11;
	msg.msg_id = 22;
	msg.src = 33;
	msg.dst = 44;
	msg.data = "this is test!this is test!this is test!";

	std::vector<char> data;

	printf("original : %d %d %d %d [%s]\n", msg.msg_type, msg.msg_id, msg.src, msg.dst, msg.data.c_str());

	msg.Serialize(data);
	msg.Deserialize(data);

	printf("result   : %d %d %d %d [%s]\n", msg.msg_type, msg.msg_id, msg.src, msg.dst, msg.data.c_str());
}


[using c-style casts for brevity!]
If your serializer is sending data between computers then you also need to worry about byte order.

Why serialize to a vector<char>? Why not to an ostream? It'll certainly make the code easier to read.
Thank you for answers. it was helpful
Registered users can post here. Sign in or register to post.