所以我有以下代码,是我想要做的简化版本。我有一个带有成员变量的类,我希望将其设置为潜在的各种不同的数据类型,具体取决于具体情况(我只是为此测试制作了一个随机结构)。我不断在memcpy函数上遇到seg错误,我不明白为什么。
#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;
}
答案 0 :(得分:5)
您的代码有多个问题,但SIGSEGV的直接原因是以下行:
memcpy(data, ptr, sizeof(ptr));
尝试将多个字节复制到未分配的指针data
。
另一方面,看起来您正试图使用完全不合理的方法在C ++中实现多态性。
答案 1 :(得分:2)
其他人提到由于使用memcpy
作为要复制的字节数,sizeof(void*)
不正确。但是,将sizeof
更改为适当的值只会让您使用memcpy
进入下一个障碍。执行此行后,您可能会遇到它:
cout<<test.data->name<<endl
原因是data->name
很可能已损坏,无效,或者如果您确实看到打印的名称,则字符串处于不稳定状态。
基本上,如果结构不是 POD 类型,使用memcpy
将结构设置为某个值是不可行的。
您的product
类的成员属于非POD类型,即std::string
。您不能简单地使用来自另一个std::string
对象的数据字节覆盖std::string
对象(这是memcpy
将要执行的操作)。
对于诸如memset
或任何C
导向函数之类的函数,可以说同样的事情,它设置用值指向的字节的字节。它们不能用于非POD类型。
与POD类型不同,只需执行这样的字节副本就会破坏目标对象。如果该对象包含,比如一个v-table,那么你真的会将目标对象翻录为碎片。
对于非POD类型,请使用适当的C ++技术,包括使用赋值(data = ptr
)。
答案 2 :(得分:0)
另外我想这可能是问题
cout<<test.data->name<<endl;
案例数据是无效指针,因此您需要在此处投射
cout<<static_cast<product *>(test.data)->name<<endl;