复制类的一部分
我想将类的一部分复制到缓冲区。我需要这个来制作一些可以查看类中是否有更改的东西,并通过网络发送它以更新服务器上的更改。
我做了一个模板类,可以备份和恢复类。现在我正在制作“寻找差异”功能。我希望用户可以定义内存块有多大。这将类分成几部分并且需要发送更少的数据。
问题是我无法将类内存的一部分复制到堆中,我无法获得正确的地址。如果我做“类的地址”+“0x04”。然后我就得不到正确的地址。
这是我制作的一个例子:
testclass test1;
testclass test2;
test1.set(1,1);
test2.set(1,2);
cout << &test1 << " " << (&test1 + 0x04) << endl; //0018FF24 0018FF44
memcpy(&test2,&test1 + 0x04,4);
test2.echo(); //Wrong data!
标题:
class testclass
{
int test,test2;
public:
void set(int a, int b) {test = a, test2 = b;}
void echo() {cout << test << " " << test2 << endl;}
};
我希望有人帮助我解决这个问题。
谢谢!
I want to copy a part of a class to a buffer. I need this to make something that can look if there are changes in a class, and send it over the network to update the changes on the server.
I made a template class that can back-up and restore classes. Now I am making the "look for differences" function. I want that the user can define how big the memory blocks will be. This split the class in parts and takes less data to send.
The problem is that I can't copy a part of the class memory to the heap, I can't get the address correct. If I do "address of the class" + "0x04". Then I don't get the correct addres.
This is an exaple that I made:
testclass test1;
testclass test2;
test1.set(1,1);
test2.set(1,2);
cout << &test1 << " " << (&test1 + 0x04) << endl; //0018FF24 0018FF44
memcpy(&test2,&test1 + 0x04,4);
test2.echo(); //Wrong data!
The header:
class testclass
{
int test,test2;
public:
void set(int a, int b) {test = a, test2 = b;}
void echo() {cout << test << " " << test2 << endl;}
};
I hope someone help me with this problem.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
基本上,你不能乱用这样的指针。您通常不能依赖编译器巧合地将有意义的数据放在那里。
如果你想要成员的地址,你应该写
&(test1.test2)
而不是&test1+0x04
因为即使 IF 是一个 int 4 个字节,并且 IF 编译器没有填充结构,并且 IF 您或其他人没有更改类的内容,则&test1+ 0x04
的真正含义“&test1
plus4*sizeof(test)
bytes”,这是达到(&test1)[4]
的另一种方式指针数组等价。另外,一般情况下,您不能对类进行
memcpy
并期望得到有意义的结果,除非它们是 POD。如果你想比较一个类的实例,你应该编写一个函数来依次比较每个成员。
您无法为此编写通用方法,因为 C++ 不是反射语言。这意味着您无法编写能够神奇地知道类成员的名称和类型的代码。
因此,如果您想像这样比较和修补数据,您将需要执行以下操作:
您必须为要修补的每个类编写类似的内容。
Basically, you can't muck around with pointers like that. You generally can't rely on the compiler to coincidentally put meaningful data there.
If you want the address of members you should write
&(test1.test2)
not&test1+0x04
because even IF an int is 4 bytes and IF the compiler hasn't padded the structure and IF you or someone else hasn't changed the contents of the class, then&test1+0x04
really means "&test1
plus4*sizeof(test)
bytes", it's another way of reaching(&test1)[4]
in terms of pointer-array-equivalence.Also, you can't
memcpy
over classes in general and expect meaningful results, unless they are POD.If you want to compare instances of a class, you should write a function which compares each of the members in turn.
You can't write a general-purpose method for this because C++ is not a reflective language. That means you can't write code which magically knows the names and types of the members of a class.
So, if you want to compare and patch data like this, you will need to do something like this:
You will have to write something like this for each class you want to patch.
神奇的 0x04 和 4 从哪里来?
如果这有效,那只是因为特定的调整和实现。
更好的更结构化的方式:
Where does the magic 0x04 and 4 come from?
If this works, it is just because of a particular alignment and implementation.
Better a more structured way:
&test1 + 0x04
表示将testclass
大小的4倍添加到test1
的地址上,得到的指针类型为testclass *。它将指向数组的第五个元素,其第一个元素位于
test1
的地址,但test1
不是数组的一部分,因此加法未定义行为。您似乎想要的是向
test1
的地址添加 4字节。例如,您可以使用((char*)&test1) + 4
来执行此操作,这会生成char*
类型的指针。请注意,该标准不保证sizeof(int)
为 4,也不保证offsetof(testclass, test2) == sizeof(int)
。您可以以
char*
或unsigned char*
形式检查任何对象的内存。但这种能力的有用性有一些限制:&test1 + 0x04
means to add 4 times the sizeoftestclass
to the address oftest1
, and the resulting pointer has typetestclass*
. It would point to the fifth element of an array whose first element is at the address oftest1
, except thattest1
isn't part of an array, so the addition has undefined behavior.What you seem to want is to add 4 bytes to the address of
test1
. You can do that for example with((char*)&test1) + 4
, which results in a pointer of typechar*
. Beware that the standard doesn't guarantee thatsizeof(int)
is 4, nor does it guarantee thatoffsetof(testclass, test2) == sizeof(int)
.You're permitted to inspect any object's memory as
char*
orunsigned char*
. But there are some limits on how useful this ability is:1)首先,你需要你的类是POD。至少你可以取出数据成员来分离结构。
2) 然后,如果需要的话选择偏移粒度 = 1、2、4 或 2^n 字节;并确定适合此要求的类型:
2^n == sizeof(chunk_type)
。例如,您希望进行字节到字节的比较,因此将指向_State
(或MyClass
参见 #1)的指针转换为所需类型: (char*)this- >m_state。这是一个函数,它尝试找到两个类中不同的第一个块,并返回其偏移量,如果没有找到差异,则返回 -1。
PS:当然,您的
chunk_type
必须定义==
运算符(这已经针对 char、int 和其他标量完成)。(我没有测试过代码)
1) At first, you need your class to be POD. At least you can take out data members to separate structure.
2) Then, if choose your offset granularity = 1, 2, 4 or 2^n bytes as necessary; and determine the type that suits this requirement:
2^n == sizeof(chunk_type)
. For example, you wish to byte-to-byte comparison, so cast you pointer to_State
(orMyClass
see #1) to desired type: (char*)this->m_state.Here is the function, that tries to find the first chunk that differs in both classes, and returns its offset or -1 if no differences found.
PS: Of course, your
chunk_type
must have==
operator defined (this done already for char, int and other scalars).(I've not tested the code)