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
Topic archived. No new replies allowed.