我正在尝试序列化一个结构,但程序崩溃了:
*** glibc detected *** ./unserialization: double free or corruption (fasttop): 0x0000000000cf8010 ***
#include <iostream>
#include <cstdlib>
#include <cstring>
struct Dummy
{
std::string name;
double height;
};
template<typename T>
class Serialization
{
public:
static unsigned char* toArray (T & t)
{
unsigned char *buffer = new unsigned char [ sizeof (T) ];
memcpy ( buffer , &t , sizeof (T) );
return buffer;
};
static T fromArray ( unsigned char *buffer )
{
T t;
memcpy ( &t , buffer , sizeof (T) );
return t;
};
};
int main ( int argc , char **argv )
{
Dummy human;
human.name = "Someone";
human.height = 11.333;
unsigned char *buffer = Serialization<Dummy>::toArray (human);
Dummy dummy = Serialization<Dummy>::fromArray (buffer);
std::cout << "Name:" << dummy.name << "\n" << "Height:" << dummy.height << std::endl;
delete buffer;
return 0;
}
答案 0 :(得分:4)
我发现此代码有两个问题:
您正在通过memcpy
struct
包含std::string
到另一个位置来调用未定义的行为。如果你memcpy
一个不仅仅是纯结构的类(例如,std::string
),它可能会导致各种各样的问题。在这种特殊情况下,我认为问题的一部分可能是std::string
有时会存储一个指向包含字符串实际内容的字符缓冲区的内部指针。如果您memcpy
std::string
,则绕过将复制字符串的字符串的普通复制构造函数。相反,您现在有两个不同的std::string
实例共享一个指针,所以当它们被销毁时,它们都会尝试删除字符缓冲区,从而导致您看到的错误。除了不做你正在做的事情之外,没有其他简单的解决办法。这根本就是不安全的。
您使用new[]
分配内存,但使用delete
删除内存。您应该使用数组删除运算符delete[]
来删除此内存,因为在其上使用常规delete
将导致未定义的行为,可能导致此崩溃。
希望这有帮助!
答案 1 :(得分:2)
将memcpy()
与std::string
类型的数据元素(或者实际上,任何非POD数据类型)一起使用是无效的。 std::string
类将实际字符串数据存储在动态分配的缓冲区中。当您memcpy()
周围的std::string
内容时,您将删除内部分配的指针并最终访问已释放的内存。
您可以通过将声明更改为:
来使代码正常工作struct Dummy
{
char name[100];
double height;
};
但是,它具有固定大小name
缓冲区的缺点。如果您想维护动态调整大小的name
,那么您需要具有更复杂的toArray
和fromArray
实现,而不执行直接内存复制。
答案 2 :(得分:0)
您正在string
来电中复制toArray
的内部缓冲区。使用fromArray
进行反序列化时,您在dummy
中“创建”第二个字符串,认为它拥有与human
相同的缓冲区。
答案 3 :(得分:0)
std :: string可能包含一个指针到包含字符串数据的缓冲区。当你调用theArray(human)时,你是memcpy()'的Dummy类的字符串,包括指向字符串数据的指针。然后当你通过memcpy()直接创建一个新的Dummy对象时,你已经创建了一个新的字符串对象,其字符串数据的指针与第一个对象相同。接下来你知道,虚拟被破坏,指针的副本被破坏,然后人类被破坏,BAM,你有一个双重自由。
通常,使用像这样的memcpy复制对象会导致各种各样的问题,比如你所见过的问题。它可能只是冰山一角。相反,您可以考虑为要序列化的每个类显式实现某种编组函数。
或者,您可以查看c ++的json库,它可以将事物序列化为方便的基于文本的格式。 JSON协议通常与自定义网络协议一起使用,您希望序列化对象以通过套接字发送。