2012-07-24 127 views
3

編輯:謝謝你的回答!我宣佈tellSomething方法的std::string返回類型,而它應該是void爲什麼刪除指向指針向量的指針會導致指針無效?

我正在絆倒自己,並指責可憐的無辜delete運營商:)!


讓我們考慮一個指向一個動態分配的vector其中包含指向動態分配的對象:

// Create the vector of pointers 
std::vector<A *>* v = new std::vector<A *>; 

// Create two objects 
A *a1 = new A; 
A *a2 = new A; 

// Populate the vector 
v->push_back(a1); 
v->push_back(a2); 

// Delete the vector 
delete v; 

// Try accessing one of the objects 
a1->tellSomething(); --> // Segmentation fault 

正如預期的那樣,如果我刪除vector,對包含的對象的delete不叫(我也證實A::~A()從未在上面的代碼中被調用),但是,最後的指令給出了分段錯誤。

我從delete v期望是兩件事情:

  • ,每包含的對象調用析構函數
  • 的容器被釋放

但是,在這種情況下,所包含的對象是指針,所以沒有調用析構函數。

此外,a1不是NULL在列表結束。

那麼,爲什麼分段錯誤?


完整示例:http://ideone.com/r8YC0


注:我不經常使用與STL容器裸指針,請考慮下面的代碼作爲一個純粹的理論例子來幫助我理解delete v指令的邏輯。

+0

它是什麼'a1-> tellSomething'在做什麼? – Wug 2012-07-24 19:15:26

+0

我相信'delete'關鍵字調用矢量的析構函數,它會依次刪除所有指針 – 2012-07-24 19:15:32

+0

這不應該發生。你怎麼知道它不在tellSomething()方法中 - 你排除了這種可能性嗎? – mathematician1975 2012-07-24 19:16:26

回答

9

你得到的崩潰是完全不相關的;你宣稱tellSomething返回std::string,但你永遠不會返回任何東西,所以你進入未定義的行爲 - 土地;該程序在釋放該向量之後崩潰的事實純屬運氣,即使在第一次調用tellSomething時也可能會崩潰。

Fixing that problem使您的程序運行良好(儘管您正在泄漏a1a2)。

順便說一句,這教你打開了所有的警告:與-Wall代碼就會給你這個潛在問題的一個明確的警告:

[email protected] ~/cpp $ g++ -Wall testwarns.cpp 
testwarns.cpp: In member function ‘std::string A::tellSomething()’: 
testwarns.cpp:12:5: warning: no return statement in function returning non-void [-Wreturn-type] 

(僅僅是爲了記錄:我個人推薦用-Wall -Wextra -ansi -pedantic進行編譯,通常一個警告可以爲你節省很多調試時間)。

+4

+1用於打開警告。 – 2012-07-24 19:19:53

+0

我喜歡用clang的警告是'-Weverything -Werror',然後是一長串'-Wno- *'參數來禁用我不在乎的警告,比如'-Wno-C++ 98-compat - WNO-C++ 98-COMPAT-pedantic'。 – bames53 2012-07-24 19:29:42

2

您的tellSomething方法缺少返回值。

將該return "";添加到該方法使您的代碼運行得很好,儘管存在內存泄漏。

+0

可能是這個。 – Wug 2012-07-24 19:18:17

8

崩潰來自一個嘗試呼叫無效std::string析構函數:

std::string tellSomething() { 
    std::cout << "A!" << std::endl; 
} 

a1->tellSomething();的調用告訴運行時預計的範圍,它然後試圖破壞自動存儲std::string。但這是無效的。

從技術上講,這是未定義的行爲,因爲你沒有返回你答應你會的東西。

+1

自從我是C++:ing以來,它已經有一段時間了,但是如何編譯這些代碼?我希望它在編譯時失敗.. – 2012-07-24 19:21:48

+1

@AvadaKedavra MSVS它確實失敗。顯然海灣合作委員會更寬鬆...... – 2012-07-24 19:23:41

+0

好吧,純粹。自從我進入海灣合作委員會以來,它的時間更長了。 +1順便說一句,很好的答案。 – 2012-07-24 19:24:38

3

刪除矢量不會刪除矢量元素。您遇到由tellSomething()在指定返回字符串時無法返回值的完全不同的問題。

http://ideone.com/Jo9zi

3

它崩潰,因爲在法聯代碼A::tellSomething你應該返回std::string你不這樣做。它與刪除無關v