2014-06-17 104 views
-4

下面的代碼:內存泄漏用的std :: string

#include <string> 

void *ptr = nullptr; 
std::string *p = new std::string(); 
*p = "1"; 
ptr = p; 
delete ptr; 

似乎使內存泄漏與下面的輸出:

21:檢測到的內存泄漏!

21:傾銷對象 - >

21:{706}正常塊在0x00723860,8個字節長。

21:數據:< Q> C8 04 71 00 00 00 00 00

21:對象轉儲完成。

這是奇怪的,因爲下面的代碼顯示沒有錯誤(作品也爲布爾):

void *ptr = nullptr; 
int *p = new int(); 
*p = 1; 
ptr = p; 
delete ptr; 

什麼我做錯了任何想法? (我需要使用「void *」指針,因爲它可能會保留不同類型的對象)。 非常感謝能幫助我的人! :)

+0

C++有更好的方法來處理不同於'void *'的類型。例如[boost :: any](http://www.boost.org/doc/libs/1_55_0/doc/html/any。html) – risingDarkness

+0

@risingDarkness我從C++開始。如果你可以給出一些其他類型的線索而不是「void *」來使用,那將會很棒! – EuskalNono

+8

這完全沒有道理:'ptr = * p;'。這甚至不應該*編譯*。關於什麼「工作」,「int」具有最微不足道的瑣碎析構函數(* none *)。 'std :: string'不能這麼說。 – WhozCraig

回答

6

(假設您的意思是ptr = p)。

如果您將void *傳遞給delete,則不會調用析構函數。
(有沒有辦法讓編譯器知道如果有一個,所以沒有辦法來調用它。)

由於std::string內部保存了動態分配的緩衝區,該緩衝區被泄露,如果析構函數ISN」叫。

您需要通過模板,boost::any,具有虛擬析構函數的通用基類或手動簿記來維護「正確」指針。

+0

這個答案沒有提到模板,這很奇怪。除非我們知道它們不能被使用(需要運行時多態性),否則模板是*明顯*,*慣用*解決方案。幾乎可以肯定的是,這比所有其他提議的機制更能解決OP的問題。 –

+0

@Konrad Rudolph:其實我提到過模板。 – risingDarkness

+1

@KonradRudolph這並不奇怪,它是老生常談。 – molbdnilo

1

根據C++標準

操作數應爲指針的對象類型或類的類型。如果是 類的類型,則操作數會上下文隱式轉換(條款 4)爲指向對象類型的指針。

並進一步在腳註有被寫

81)這意味着,一個對象可以不使用 void *類型的指針,因爲空隙不是一個對象類型被刪除。

所以程序的行爲是不確定的。既不調用類型爲std::string的對象的析構函數也不調用操作符函數,因爲對象的大小未知。