2009-08-19 38 views
1

編輯:問題解決了。這是另一種情況,問題並不是它看起來真的那樣。線索是@ 0xfeeefefe作爲指向對象的指針。這是在釋放內存時由Windows API函數返回的地址......表示正在操作的對象已被刪除。查找我的段錯誤的來源

我在嘗試從std :: map中刪除一個值時收到一個段錯誤,但是我不知道爲什麼。從調試器(GDB)我看到:

Program received signal SIGSEGV, Segmentation fault. 
0x0048785f in std::less<irr::gui::IGUIWindow*>::operator()(irr::gui::IGUIWindow* const&, irr::gui::IGUIWindow* const&) const (this=0x258ab04, [email protected], [email protected]) 
at C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_function.h:227 
227   { return __x < __y; } 

但怪異的一部分是這兩個輸入值以下檢查:

(gdb) x 0x22f778 
0x22f778:  0x025e1ef8 
(gdb) x 0xfeeefefe 
0xfeeefefe:  0x025e1ef8 

一些背景資料: 地圖是一個指針的指針的映射。具體而言,該鍵是一個指向gui系統中的窗口的指針,該值是指向可能發送要打印到該窗口的信息的對象的指針。還有一個從可調試對象到窗口的逆映射。原因是,如果窗口關閉,需要通知可調試對象,以便通過嘗試向其發送數據不會浪費時間。反向映射是這樣的,當管理者(這個代碼所在的類)從可調試對象接收到一個數據包時,它知道哪個窗口打印信息。

所以問題是爲什麼會比較兩個指針值,return(0x025e1ef8 < 0x025e1ef8)導致錯誤?

我只嘗試在我的代碼中的某一點擦除事物,並且它不在循環中,因此沒有任何迭代器會損壞。我也只是在其他地方將東西插入到地圖中,並且在插入和刪除東西時我會打印出一些痕跡,並且我看不到任何錯誤。

我知道這些信息還不足以真正幫助,但代碼非常龐大,我不確定我能做些什麼來追蹤問題。如果有任何建議,我會很樂意提供更多信息。我將粘貼代碼的一些部分以便快速瞭解發生了什麼。希望在這裏有東西來表明我的問題是什麼。

這裏是有問題的部分

case EGET_ELEMENT_CLOSED: 
{ 
    IGUIWindow* window = 
     static_cast<IGUIWindow*>(event.GUIEvent.Caller); 

    if(m_debugMap.find(window) != m_debugMap.end()) 
    { 
     IGuiDebuggable* debug = m_debugMap[window]; 
     debug->removeListener(this); 

     cout << "closing window: " << window << " attached" 
       " to debuggable: " << debug << endl; 

     m_debugMap.erase(window); /// segfault here 
     m_conMap.erase(debug);  /// if above line commented, segfault here 
    } 

    m_eventMap.erase(window); /// if above block commented, segfault here 
    window->remove(); 
    return true; 
} 

這裏的地方一個元素被添加到地圖

IGUIElement* winElmnt = 
        m_env->getRootGUIElement()->getElementFromId(0,false); 

IGUIElement* editElmnt = winElmnt->getElementFromId(1); 
IGUIWindow*  window  = static_cast<IGUIWindow*>(winElmnt); 

cout << "CModelTesterGui: adding " << window << "(" << winElmnt 
    << ") to the debug map with edit box " << editElmnt << endl; 

m_conMap[debug]    = static_cast<IGUIEditBox*>(editElmnt); 
m_debugMap[window]   = debug; 

window->setID(-1); 
debug->addListener(this); 

正如你可以看到我打印出來的是什麼地址的一部分進入以及試圖從地圖中刪除的內容,並且它們與我預期的一致,所以我並不試圖抹去不存在的值或任何東西。

哦,還有最後一張紙條。這是一個奇怪的怪癖。如果我只打開一個窗口(即只添加一個元素到地圖),我可以把它擦掉。只有在向地圖添加兩個或更多元素之後,試圖擦除其中一個元素纔會導致分段錯誤。

回答

2

看起來像段錯誤發生在實際比較之前試圖取消0xfeeefefe

FEEEFEEE微軟的 HeapFree()用於標記釋放堆內存(1)

哪些類型的__ x和__y?你可以驗證寫入__x__y的初始值,然後在內存位置上觀看任何更改嗎?另外,如果您可以在HeapFree函數上放置一個斷點,您可能會收到錯誤的內存引用。

+0

我試圖把一個斷點HeapFree但它說這個函數沒有定義,可能這個名字被破壞了,我會看看我能否找到它 – cheshirekow 2009-08-19 03:13:05

+0

OMG,謝謝,這正是我需要的線索,我無法找到一種方法來獲得HeapFree的蹤跡,但我認爲有一堆正在被釋放(並且它不應該),並且提醒我這個問題。所以這個類是引用計數的,並且 - > removeListener導致源對象放棄一個引用......但是它在課堂上第一次被添加時沒有正確地抓住參考 – cheshirekow 2009-08-19 03:35:36

2

哦,還有最後一張紙條。這是一個奇怪的 怪癖。如果我只打開一個窗口(即 只添加一個元素到地圖),我可以 抹掉它。只有在向地圖添加 兩個或多個元素之後, 纔會嘗試刪除其中一個元素導致 分段錯誤。

奇怪的怪癖通常代表記憶問題。你嘗試過運行valgrind嗎?

你插入一個克隆嗎?指針在插入和刪除地圖之間的某處被刪除?

+0

我在窗口:/ ... – cheshirekow 2009-08-19 02:28:02

+0

CR * P :-(15chars – Tom 2009-08-19 02:28:58

+0

然後使用Visual Studio調試器 – leiz 2009-08-19 02:29:53

1

我在看你的追蹤,和我看到的地方說:

__X = @ 0x22f778,__y = @ 0xfeeefefe

這似乎表明,__X和__y是引用。

既然如此,試圖測試(__x < __y)可能會取消引用它們,並且取消引用0xfeeefefe可能不是一件好事情,除非您的計算機已安裝beaucoup內存。

+0

是的,看凱西的答案,看起來它是一個虛擬地址,用於b贏得API – cheshirekow 2009-08-19 03:51:25

相關問題