简体   繁体   English

为什么这个 memcpy 不起作用?

[英]Why doesn't this memcpy work?

So I have the following code, a simplified version of what I want to do.所以我有以下代码,我想做的简化版本。 I have a class with a member variable that I want to set to potentially a variety of different data types, depending on the situation (i just made a random struct for this test).我有一个 class 的成员变量,我想根据情况将其设置为可能的各种不同的数据类型(我只是为此测试创建了一个随机结构)。 I keep getting seg faults on the memcpy function though, and I have no idea why.我一直在 memcpy function 上遇到段错误,我不知道为什么。

 #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;
}

Your code has multiple issues, but a direct cause of SIGSEGV is following line: memcpy(data, ptr, sizeof(ptr)); 您的代码有多个问题,但是SIGSEGV的直接原因是以下行: memcpy(data, ptr, sizeof(ptr)); which tries to copy a number of bytes into unallocated pointer data . 它试图将多个字节复制到未分配的指针data

On a side note, it looks like you are trying to achieve polymorphism in C++ using completely inapproriate methods. 附带说明一下,您似乎正在尝试使用完全不合适的方法在C ++中实现多态。

Others have mentioned that the memcpy is not correct due to using sizeof(void*) as the number of bytes to copy. 其他人提到memcpy是不正确的,因为使用sizeof(void*)作为要复制的字节数。 But changing the sizeof to an appropriate value will just have you hit the next stumbling block with using memcpy . 但是将sizeof更改为适当的值只会使您使用memcpy到达下一个绊脚石。 You would probably encounter it as soon as you execute this line: 执行此行后,您可能会遇到它:

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

The reason is that data->name is more than likely corrupted, invalid, or if you did actually see a name printed, the string is in an unstable state. 原因是data->name很可能已损坏,无效,或者如果确实看到了打印的名称,则字符串处于不稳定状态。

Basically, using memcpy to set a struct to a certain value isn't going to work if the struct is not a POD type. 基本上,如果该结构不是POD类型,则使用memcpy将结构设置为某个值将不起作用。

What is a POD type? 什么是POD类型?

POD updates for C++ 11 C ++ 11的POD更新

Your product class has a member that is a non-POD type, namely std::string . 您的product类具有一个非POD类型的成员,即std::string You cannot simply overlay a std::string object with bytes of data from another std::string object (which is what that memcpy will be doing). 你不能简单地叠加一个std::string对象从另一个数据字节std::string对象(这是什么memcpy会做)。

The same thing can be said for functions such as memset or any C oriented function that sets the bytes of what is pointed to with values. 对于诸如memset函数或任何设置值所指向的字节的面向C的函数,都可以说相同的话。 They cannot be used on non-POD types. 它们不能用于非POD类型。

Unlike POD types, just doing a copy of bytes like that will corrupt the destination object. 与POD类型不同,仅执行类似的字节副本将损坏目标对象。 If that object contained, say a v-table, then you really would be ripping the destination object to shreds. 如果包含该对象(例如v表),那么您实际上将把目标对象撕成碎片。

For non-POD types, use the proper C++ techniques, which include using assignment ( data = ptr ). 对于非POD类型,请使用适当的C ++技术,其中包括使用赋值( data = ptr )。

Also I suppose it could be problem here 我也想这可能是个问题

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

case data is void pointer so you need cast here 案例数据为空指针,因此您需要在此处进行投射

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

I know this is an old post, but I don't like any of the answers, so for future readers.我知道这是一篇旧文章,但我不喜欢任何答案,所以对于未来的读者。

When you cast an object to a void*, you loss the type information associated with it.当您将 object 强制转换为 void* 时,您会丢失与其关联的类型信息。 That is why you can't use sizeof with a void* ptr.这就是为什么您不能将 sizeof 与 void* ptr 一起使用。 (This is probably also why memcpy doesn't do it this way). (这可能也是 memcpy 不这样做的原因)。 I think what you need here is to write a Template class.我认为您需要在这里编写一个模板 class。 Then the code will know the type and the code should work.然后代码将知道类型并且代码应该可以工作。

template<class T>
class object
{
public:
        void setData(T *ptr);
        T* data;
};


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM