簡體   English   中英

為什么這個 memcpy 不起作用?

[英]Why doesn't this memcpy work?

所以我有以下代碼,我想做的簡化版本。 我有一個 class 的成員變量,我想根據情況將其設置為可能的各種不同的數據類型(我只是為此測試創建了一個隨機結構)。 我一直在 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;
}

您的代碼有多個問題,但是SIGSEGV的直接原因是以下行: memcpy(data, ptr, sizeof(ptr)); 它試圖將多個字節復制到未分配的指針data

附帶說明一下,您似乎正在嘗試使用完全不合適的方法在C ++中實現多態。

其他人提到memcpy是不正確的,因為使用sizeof(void*)作為要復制的字節數。 但是將sizeof更改為適當的值只會使您使用memcpy到達下一個絆腳石。 執行此行后,您可能會遇到它:

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

原因是data->name很可能已損壞,無效,或者如果確實看到了打印的名稱,則字符串處於不穩定狀態。

基本上,如果該結構不是POD類型,則使用memcpy將結構設置為某個值將不起作用。

什么是POD類型?

C ++ 11的POD更新

您的product類具有一個非POD類型的成員,即std::string 你不能簡單地疊加一個std::string對象從另一個數據字節std::string對象(這是什么memcpy會做)。

對於諸如memset函數或任何設置值所指向的字節的面向C的函數,都可以說相同的話。 它們不能用於非POD類型。

與POD類型不同,僅執行類似的字節副本將損壞目標對象。 如果包含該對象(例如v表),那么您實際上將把目標對象撕成碎片。

對於非POD類型,請使用適當的C ++技術,其中包括使用賦值( data = ptr )。

我也想這可能是個問題

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

案例數據為空指針,因此您需要在此處進行投射

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

我知道這是一篇舊文章,但我不喜歡任何答案,所以對於未來的讀者。

當您將 object 強制轉換為 void* 時,您會丟失與其關聯的類型信息。 這就是為什么您不能將 sizeof 與 void* ptr 一起使用。 (這可能也是 memcpy 不這樣做的原因)。 我認為您需要在這里編寫一個模板 class。 然后代碼將知道類型並且代碼應該可以工作。

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