2012-05-14 32 views
0

執行下面的C++代碼後,我運行valgrind --leak-check=full以檢查是否有任何內存泄漏。結果是0字節在出口處使用,沒有泄漏是可能的Valgrind不會在「刪除陣列」上報告內存泄漏

但是,後來我發現我忘了在析構函數裏面使用delete[] x而不是delete x

我搜索了一些解釋(例如:delete vs delete[] operators in C++),我讀到的一切說使用delete沒有[]可能會導致內存泄漏,因爲它要求只是爲數組中的第一個對象的析構函數。

我改變了代碼刪除[]和Valgrind輸出是相同的(如預期)。但是現在我很困惑:「valgrind有沒有問題,或者delete真的可以正常工作,即使沒有運營商[]

#include <iostream> 
#include <string.h> 
using namespace std; 
class Foo { 
    private: char *x; 
    public: 
    Foo(const char* px) { 
     this->x = new char[strlen(px)+1]; 
     strcpy(this->x, px); 
    } 
    ~Foo() { 
     delete x; 
    } 
    void printInfo() { cout << "x: " << x << endl; } 
}; 
int main() { 
    Foo *objfoo = new Foo("ABC123"); 
    objfoo->printInfo(); 
    delete objfoo; 
    return 0; 
} 
+0

您提到的問題的答案沒有提及內存泄漏。事實上,他們說的和阿爾斯在下面說的一樣。那麼你爲什麼說*「我讀過的所有內容都表示,如果不使用[],則會導致內存泄漏。」*? –

+2

另外,在你的程序標誌上使用valgrind 3.2.1,有一個'不匹配的free()/ delete/delete []'。這不是內存泄漏,但它是一個錯誤。 –

+0

據瞭解,例如,當數組包含'char'等內置類型時,MSVC恰好爲'delete x'和'delete [] x'生成相同的代碼。該代碼對於具有析構函數的類類型是*不同*。 –

回答

7

使用刪除而不[]導致內存泄漏。

不,它會導致未定義的行爲

您使用new []分配並使用delete取消分配的程序有未定義的行爲。其實,你很幸運(相當不幸),它並不顯示一些奇怪的行爲。

作爲便箋,您還需要按照Rule of Three爲您的課程。目前,你不這樣做,並在不久的將來呼喚麻煩。

+0

Upvote for「rather unlucky」。 –

+0

能不能說得更好,但我會引用常見問題解答,以便提問者可以參考正在發生的事情:「程序員不是編譯器的責任,以便在新的T [n]和delete []之間建立連接如果你弄錯了,編譯器和運行時錯誤信息都不會被編譯器生成,堆損壞可能會導致,或者更糟的是,你的程序可能會死掉。 http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.12 –

+0

Stephen,是的,我知道這是程序員的責任,我也知道後果。我只想了解valgrind爲什麼找不到可能的泄漏。 –

2

deletedelete[]之間的主要區別不在於內存釋放,而在於析構函數調用。

雖然正式未定義的行爲,實際上它會或多或少的工作...除了delete只會調用第一項的析構函數。

作爲一個側面說明,你可能會得到一個問題:

#include <iostream> 

struct A{ 
    ~A() { std::cout << "destructor\n"; } 
}; 

int main() { 
    A* a = new A[10]; 
    delete a; 
} 

有點像:

*** glibc detected *** ./prog: munmap_chunk(): invalid pointer: 0x093fe00c *** 
======= Backtrace: ========= 
/lib/libc.so.6[0xb759dfd4] 
/lib/libc.so.6[0xb759ef89] 
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/libstdc++.so.6(_ZdlPv+0x21)[0xb77602d1] 
./prog(__gxx_personality_v0+0x18f)[0x8048763] 
./prog(__gxx_personality_v0+0x4d)[0x8048621] 
======= Memory map: ======== 

看到它ideone

+0

我認爲這是OP的爭論,因爲他的'delete'調用是在析構函數中。 –

+0

當「刪除新的T [n]」時,大多數實現將(幸運地)失敗,因爲它們將大小存儲在分配前面,因此略微偏移了用於調用基礎原始內存管理器的指針 – PlasmaHH