2012-02-29 45 views
2

在我的代碼,我有我的地圖鍵使用結構地圖時:分段錯誤刪除與結構是按鍵

struct index{ 
    int x; 
    int y; 
    int z; 
    bool operator<(const index &b){ 
    bool out = true; 
    if (x == b.x){ 
     if (y == b.y){ 
     out = z < b.z; 
     } else out = y < b.y; 
    } else out = x < b.x; 
    return out; 
    } 
}; 

我用的地圖是:

map<index,set<std::pair<int, int> > > tBoxes; 

當程序結束運行時,我嘗試釋放內存,當程序嘗試刪除映射時,出現分段錯誤。用GDB我得到:

#0 std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (this=0x63b900, 
    __x=0x404057eb274ede6c) 
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264 
#1 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
    this=0x63b900, __x=0x7d31110) 
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264 
#2 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
    this=0x63b900, __x=0x7d30e30) 
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264 
#3 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
    this=0x63b900, __x=0x7d30b50) 
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264 
#4 0x000000000041ed2f in std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_erase (
    this=0x63b900, __x=0x7d272c0) 
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1264 
#5 0x0000000000418237 in clear (this=0x63b3e0, 
    __in_chrg=<value optimized out>) 
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:692 
#6 clear (this=0x63b3e0, __in_chrg=<value optimized out>) 
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:501 
#7 membrane::~membrane (this=0x63b3e0, __in_chrg=<value optimized out>) 
    at memMC.cpp:135 
#8 0x0000000000421658 in __tcf_5() at main.cpp:7 
#9 0x000000378ea334f5 in exit() from /lib64/libc.so.6 
#10 0x000000378ea1d99b in __libc_start_main() from /lib64/libc.so.6 
#11 0x0000000000402309 in _start() 

而且使用的valgrind(運行$valgrind -v --track-origins=yes --leak-check=yes --tool=massig --tool=memcheck --read-var-info=yes --log-file=error.txt ./mem)我得到:

==2561==  in use at exit: 0 bytes in 0 blocks 
==2561== total heap usage: 3,346,323 allocs, 3,346,323 frees, 98,851,279 bytes allocated 
==2561== 
==2561== All heap blocks were freed -- no leaks are possible 
==2561== 
==2561== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) 
--2561-- 
--2561-- used_suppression:  4 dl-hack3 
==2561== 
==2561== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) 

,因爲它並沒有告訴我任何事情是煩人。

我曾嘗試手動清除地圖(在打印一些輸出,可能提供一些線索:

while (tBoxes.size() > 0){ 
    printf ("%i ", (*tBoxes.begin()).first.x); 
    printf ("%i ", (*tBoxes.begin()).first.y); 
    printf ("%i\n", (*tBoxes.begin()).first.z); 
    while ((*tBoxes.begin()).second.size() > 0){ 
    printf ("a\n");  
    tgBit1 = (*tBoxes.begin()).second.begin(); 
    (*tBoxes.begin()).second.erase(tgBit1); 
    printf ("b\n"); 
    } 
    tBoxes.erase(tBoxes.begin()); 
} 
tBoxes.clear(); 
tNextBoxes.clear(); 

和所有我能收集的是,刪除崩潰時,我從0和增加x 1 ?這是爲什麼發生,是有辦法使用明確()

編輯除了清除該地圖發生之後我刪除集的內容

我發現了這個錯誤。我使用的矢量之一未正確設置,實際上大小爲0.然而,我仍然訪問該矢量中的元素。

的載體是double值和I由一個框大小劃分並將結果舍入至確定tBox把在一對後使用該值。我假設我得到的無效值在index使用。問題依然存在,當我試圖訪問這個元素時,爲什麼程序不會崩潰?

+3

你可以發佈一個小編譯程序,再現呢? – hmjd 2012-02-29 16:12:14

+0

不清楚你的意思是你將x從0遞增到1.這是你的鑰匙之一嗎?在這種情況下這是不允許的,鍵必須保持不變。這會弄亂訂單。 – BoBTFish 2012-02-29 16:12:58

回答

2

我的猜測是在你的程序中某處發生了某種堆/棧損壞,它只在你的映射試圖訪問一個錯誤的指針/迭代器時纔會顯現出來。看看最後一個被刪除的迭代器(0x404057eb274ede6c),它與先前的迭代器值(0x7d31110)相比看起來很可疑。

至於Valgrind爲什麼沒有檢測到這種腐敗?我對這個工具不是很熟悉,但是SE上的this question指出另一個Valgrind未能檢測到「顯而易見」的不良行爲並且建議其他東西來幫助檢測它的案例。

我會盡量減少崩潰,儘可能少的代碼。在另一個項目中創建一個小測試用例,並查看崩潰是否仍然發生。以調試模式運行和/或使用額外的內存檢查來查看是否可以捕獲內存損壞(假設它就是這樣)。

更新編輯:

假設你正在使用std::vector::operator[]則此方法不執行任何邊界檢查,並會很樂意讓你嘗試訪問不存在的元素。我相信這被定義爲未定義的行爲,不幸的是,一個可能的結果是沒有任何反應。

如果您希望或需要檢查邊界,請使用std::vector::at(),請參閱this question瞭解一些詳細信息。通常,您只使用[]當你知道使用的索引是在邊界,就像在一個迭代循環或當索引手動檢查。

+0

非常感謝您的回答。最終,這個錯誤是其他地方(我會更新我的問題)。但是你可以用一些方便的工具來玩遊戲。 – Yotam 2012-03-01 09:42:49