我在這裏結束了我的工作:我有一個單線程C++程序。這裏有一些經驗數據和背景信息,我試圖強調最重要的關鍵字;單線程C++函數調用中的undebuggable非確定性heisenbug
- 我說的是整款不沒有任何系統調用,比內存(去)分配調用標準C++庫可以執行其他(
std::set
s爲參與)。這是一個純粹邏輯的算法。 - 這個的行爲應該是確定性的,這取決於輸入,我不會改變。
- 如果該錯誤自身出現,程序就會看起來像無限循環似乎開始分配內存超出任何綁定。
- 該錯誤不不清單本身不出所料,我可以在命令行運行程序,有時(也許30%-50%)的bug本身表現,否則,一切就順利且正確地運行作爲我可以告訴。
- 一旦我不是直接從提示中運行程序,而是在gdb或valgrind中,錯誤消失了,程序永遠不會死亡。
- 現在是最好的部分:我將問題追溯到(模板化的)非虛擬成員函數調用。只需要之前撥打電話,我打印一條信息到
std::cout
,其中我可以在終端看到。 第一行裏面的函數還有一條調試消息,這是從來沒有顯示的。
我沒有看到任何合理的解釋。也許你可以想出一個想法如何繼續。
編輯:代碼的顯著行,我改變了行號,所以我們可以參考它們並省略無關的部分,所以不能代表一切,似乎讓最好的感覺。
a.cpp
10 std::set<Array const*>* symbols;
11 std::set<Array const*> allSymbols;
12 symbols = &allSymbols;
// ... allSymbols are populated with std::inserter
15 std::cout << "eval; cd = " << &cd << ", cg = " << &cd.cg << std::endl;
16 senderConstraints = cd.cg.eval(*symbols);
b.cpp
31 template <typename ArrayContainer>
32 ConstraintList eval(ArrayContainer const request) {
33 std::cout << "inside eval ... going to update graph now" << std::endl;
輸出的最後一行是:
eval; cd = 0x2e6ebb0, cg = 0x2e6ebc0
那麼它困在無限循環。
如果你真的確定這不是一個競爭條件(效果看起來完全像你所描述的),我會轉儲我的對象的狀態,以查看哪個狀態導致錯誤狀態。一些錯誤的初始化順序也會導致這種行爲。 –
代碼會有所幫助,否則這是不可能告訴任何事情的。然而,「bug在調試器中奇蹟般地消失了」通常指向一個「if(ptr!= NULL)do_something(); '和一個非初始化變量。如果內存位置偶然爲零,則不會發生該錯誤,否則會發生。調試器對所有**變量進行初始化(即使是你沒有的變量),所以這個bug「神奇地消失了」。 – Damon
您可以嘗試使用['strace'](http://linux.die.net/man/1/strace)跟蹤系統調用(某些可能隱藏在系統庫中)。另外考慮添加** lot **的調試打印,越多越好。 –