2016-01-21 119 views
1

所以我有以下代码,我想要做的简化版本。我有一个带有成员变量的类,根据具体情况(我为此测试创建了一个随机结构),我想将其设置为各种不同的数据类型。尽管我一直在memcpy函数上发生seg错误,但我不知道为什么。为什么这个memcpy不工作?

#include <cstdlib> 
#include <iostream> 
#include <assert.h> 
#include <string> 
#include <string.h> 
#include <stdio.h> 
using namespace std; 

struct product 
{ 
     int price; 
     string name; 
}; 


class object 
{ 
public: 
     void setData(void *ptr); 
     void* data; 
}; 


void object::setData(void *ptr) 
{ 
     assert(ptr); 
     memcpy(data, ptr, sizeof(ptr)); 
} 


int main() 
{ 
     product* bag; 
     product ba; 
     bag = &ba; 
     bag->price = 5; 
     bag->name = "bag"; 

     object test; 
     test.setData(bag); 

     cout<<test.data->name<<endl; 

     return 0; 
} 
+4

'sizeof(ptr)'?????你期望这是什么? –

+1

另外 - 你不能只是'memcpy'一个字符串对象。 –

+1

即使你的'sizeof'正确,你也不能在非POD类型上使用memcpy,比如你的'product'类。 – PaulMcKenzie

回答

5

你的代码有多种问题,但SIGSEGV的直接原因是以下行: memcpy(data, ptr, sizeof(ptr));它试图字节数复制到未分配的指针data

在一个方面说明,它看起来像你试图在完全不正确的方法中使用C++实现多态。

0

此外,我想这可能是这里的问题

cout<<test.data->name<<endl; 

情况下,数据是无效的指针,所以你需要在这里施展

cout<<static_cast<product *>(test.data)->name<<endl; 
2

也有人提到,memcpy是不正确的,由于使用sizeof(void*)作为要复制的字节数。但是将sizeof更改为合适的值将会使您使用memcpy仅次于下一个绊脚石。你可能会因为很快会遇到它,你执行这行:

cout<<test.data->name<<endl 

的原因是data->name超过可能损坏,无效的,或者如果你没有真正看到一个名字印,字符串处于不稳定状态。

基本上,如果结构不是POD类型,则使用memcpy将结构设置为某个值将不起作用。

What is a POD type?

POD updates for C++ 11

product类有一个成员是一个非POD类型,即std::string。您不能简单地将std::string对象与另一个std::string对象(这是memcpy将执行的操作)的数据字节重叠。

对于诸如memset或任何C的函数,可以说同样的事情,该函数用值来设置指向的字节。它们不能用于非POD类型。

与POD类型不同,只是复制像这样的字节会破坏目标对象。如果这个对象包含了一个V表,那么你真的会把目标对象撕成碎片。

对于非POD类型,请使用适当的C++技术,其中包括使用赋值(data = ptr)。

+0

就像它很有趣,'std :: string'几乎是** POD。唯一阻止它成为POD的东西是不同的访问控制,但这不太可能导致'memcpy'的任何问题。 – SergeyA

+0

对不起,不得不赞成引用过时的POD定义。 – SergeyA

+0

有一个非平凡的析构函数也可以防止“std :: string”变成“几乎POD”。 – PaulMcKenzie