2017-01-10 88 views
-4

我只是想出於好奇。我有一個構造函數和一個拷貝構造函數的結構,並嘗試使用main中的拷貝構造函數初始化結構體,同時在主體中實現對指向結構體的指針的內存分配。複製構造初始化工作正常,但是當我嘗試在主返回之前釋放它時,它會在堆中導致斷言錯誤。結構上的內存分配和複製構造函數

#include <stdio.h> 
    #include <malloc.h> 

    typedef struct tagInfo 
    { 
     int iX; 
     int iY; 

     tagInfo() {}; 

     tagInfo(int x, int y) 
      : iX(x), iY(y) {}; 

     ~tagInfo() {}; 

    }INFO; 

    int main (void) 
    { 
     INFO* pInfo = (INFO*)malloc(sizeof(INFO)); 

     pInfo = &INFO(10, 10); 

     free(pInfo); 

     return 0; 
    } 

如何安全地釋放上述指針而不引起斷言錯誤?

+4

不要垃圾郵件的標籤!這不是有效的C代碼! – StoryTeller

+0

看到它是C++,你應該使用'new' /'delete'。除此之外 - 存儲一個臨時的內存地址,然後使用它(在'free'中)是UB(永遠不會釋放malloc'ed空間來創建內存泄漏)。 –

+2

通過將C習語混合到C++代碼中,而沒有清楚地理解其意義,您正在弄得一團糟。很好地學習C++的方法不是通過試驗和錯誤,而是從底層開始,接近它,而沒有以前學過的語言的偏見。 [選一本好書](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)適合初學者,並一步一步接受。 – StoryTeller

回答

0

我認爲基本的誤解是一個拷貝構造並不一個對象的內容複製到相同類型的(已經存在的)其他對象,而是生成一個新的對象,該對象被初始化基於要複製的對象的內容。

在您的代碼中,您使用mallocINFO類型的對象預留內存,並讓pInfo指向該內存。

接下來,pInfo = &INFO(10, 10)您在堆棧上(而不是在堆上)實例化一個INFO類型的新對象,並讓pInfo指向此對象(位於堆棧上!)的內存地址。順便說一句,你沒有提及你的malloc -ed內存,因爲指針pInfo不再指向malloc -ed地址,而是指向新對象。

free(pInfo)是至關重要的,因爲你釋放一個內存地址,它之前沒有被分配到malloc

其實,你應該做到以下幾點:

INFO* pInfo = new INFO(10, 10); 
... 
delete pInfo; 
+0

謝謝!這是我正在尋找的答案類型!我知道我應該在C++代碼中使用新的刪除,但我只是想用malloc和free來試用它,並進行比較。感謝您的酷! –

2

mallocfree不應該在C++中使用,因爲它們不處理對象的構造/銷燬。


在現代的C,如果你要建模特有的股權,或std::shared_ptr如果要模擬共享所有權 ++,你應該使用std::unique_ptr - 這些被稱爲「智能指針」並提供一個安全的方式管理動態內存,自動處理釋放/銷燬。例如:

int main (void) 
{ 
    auto pInfo = std::make_unique<INFO>(10, 10); 

    return 0; 
} 

如果你真的想下去手動內存管理的道路,就必須使用new(用於分配+建設)delete(爲釋放+毀滅)。例如:

int main (void) 
{ 
    INFO* pInfo = new INFO(10, 10); 
    delete pInfo; 

    return 0; 
} 
0

在一般情況下,你可以做到這一點與放置新的,但它是非常氣餒:

// allocate 
void* pInfoMem = malloc(sizeof(INFO)); 
// construct 
INFO* pInfo = new(pInfoMem) INFO(10, 10); 

// destruct 
pInfo->INFO::~INFO(); 
// free 
free(pInfoMem); 

但隨後你需要在釋放之前手動調用析構函數。

這是很容易只是做(其它答案提):

INFO* pInfo = new INFO(10, 10); 
delete pInfo;