2012-10-24 60 views
1

如果我們把這個例子:結束迭代器和分段錯誤

std::map<int,foo*> intmap; 
fillMap(intmap); 

// I will force this to end(), in real life this could be a "find" output 
std::map<int,foo*>::iterator iter = intmap.end(); 
if(iter->second != 0) 
    iter->second->whatever(); 

我有段錯誤(這是預期的,例如不檢查「!ITER = intmap.end()」 故意)在「whatever()」調用上但不在「 - > second」空指針檢查上:它是預期的行爲嗎?這個seg會在「whatever()」調用中系統地出錯,還是依賴於特定的運行時間內存條件?

在此先感謝您的意見。 賈科莫

回答

0

無法提領的「結束」迭代器。請記住,iter->(*iter).大致相同;也就是說,有一個解除引用。

0

提領end()迭代器是一個未定義的行爲。它可能會或可能不會崩潰。

您必須檢查的find返回值是這樣的:

if(iter != intmap.end()) 
    iter->second->whatever(); 
5

提領end()和過去-end迭代器的STL容器是未定義的行爲。沒有什麼可以撥打預計。一切都可以發生,甚至可以工作。 它可能取決於諸如編譯器/庫/操作系統版本,運行時環境狀態,調試/發佈版本等諸多因素。因此,如果您執行髒兮兮的禁止操作,則永遠不應該假定會發生什麼情況。

0

提領過去的最末端迭代器的結果是不確定的當然行爲,所以沒有什麼保證它會做。

但是,它可以是有益的(在調試情況下非常有用)要考慮什麼是可能發生的。關聯容器的典型實施方案是作爲節點的一二進制樹,其中每個節點包含指向在迭代順序的nextprevious節點,以及迭代器是圍繞一個指向節點薄包裝。類似地,list被實現爲雙向鏈表,其中每個節點包含指向nextprevious節點的指針。由於前端迭代器需要可減少,所以最簡單的實現是指向一個總是存在的節點,其指針指向容器中的最後一個節點。

因爲過去的這個最末端節點需要始終存在,即使是空的容器,最簡單的實現方式是把它放在容器類本身裏面,大部分圖書館實現將做到這一點。因此,它的存儲是自動的(本地函數)存儲,並且它將是默認構造的,所以解引用過去最終迭代器會給堆棧垃圾。

我們可以通過比較指針檢查:

#include <map> 
#include <iostream> 
int main() { 
    std::map<int, int> m; 
    std::cout << &m << ' ' << &*m.end() << ' ' << &m + 1 << '\n'; 
} 

0xbf990034 0xbf990048 0xbf99004c 

正如你可以看到,在過去的最末端節點存儲包含在map的堆疊封裝內。