2009-04-29 34 views
1

在Metrowerks CodeWarrior調試器中,是否有任何簡單的方法查看STL std::list<T>中的數據?我可以通過查看錶達式,如如何檢查CodeWarrior調試器中的STL列表?

instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_.prev_->data_ 

我可以展開的小「+」號旁邊的結構成員走列表中的元素在一段時間,但查看靠近列表的開頭或結尾數據這是很乏味的,在大約20-30個元素之後,樹對於調試器窗口來說太寬了。我正在研究的名單有2000多個元素。

CodeWarrior調試器不支持表達式中的調用函數,所以我不能檢查(++(++instances.begin()))或某些值。我只能看結構成員,這些結構名稱很長且不方便。

調試器窗口也被限制爲大約245個字符,所以我不能編寫腳本來生成一個可擴展到第N個節點的可笑的長表達式。

我試圖調試一個需要幾個小時浸泡重現的問題,所以任何需要增加代碼,重新編譯和重新編譯的東西都不會很有幫助。如果沒有其他選擇,那麼我可能必須這樣做。

回答

1

這絕對不是一個「簡單的方法」(它可能並不比「+」中的操作更簡單),但是我發現它在某些情況下比處理監視視圖更有幫助。它也可能允許您在非常糟糕的情況下進行調試(無論出於何種原因,或者只有二進制內存轉儲文件的地方,監視視圖幾乎無法運行)。

有了一個std ::列表中,你通常有一個看起來像這樣在內存中執行(請參閱列表<爲>具體如有必要):

 
struct List 
{ 
    Node * next; 
    Node * prev; 
    size_t size; 
} 

template 
struct Node 
{ 
    Node * next; // last node will point to list rather than another node 
    Node * prev; // first node will point to list rather than another node 
    T payload; // e.g. in a std::list this would be a Foo * payload 
} 

注意,next和prev可能在在您的實施中相反的順序。

& myList在大多數實現中基本上等價於「end()」。

如果您使用內存視圖,您可以在&附近戳myList。這會讓你找到myList.prev或myList.next指針的值,然後改變內存視圖來查看它。然後分別到達列表中的最後或第一個節點。一旦你到達一個節點,你可以看prev,next或payload,然後轉到上一個或下一個;起泡,沖洗,重複。如果你最後回到& myList,你知道你遍歷了整個事情。

痛苦無聊?有可能。但是,您對stl實現有很多熟悉,在某些情況下可以輕鬆「看到」可能的stomps,並且當所有其他可能性飛出窗外時,這是一項非常有用的技巧。

(請您去過的地方註釋,它真的很容易混淆。)

0

調試器肯定會多很多STL友好。我對CodeWarrior並不熟悉,但您是否可以根據調試窗口調用的任何函數?或者它更像是我用過的其他調試器,如果程序已經終止,你(1)不能調用函數(ABORT,segfault,...)和(2)不能調用涉及模板擴展的函數(可能需要向圖像添加代碼),但是(3)如果代碼在斷點處停止,可以調用靜態鏈接的函數?

在後一種情況下,您可能希望向您的代碼中添加一個或多個非模板化函數,將list<T>複製到T的C風格數組中,以獲取您感興趣的特定類型。如果可以調用調試窗口中的那種函數,做到這一點,然後檢查數組元素以找出列表中的內容。如果您無法從調試窗口調用該函數,則可能需要在代碼中將該函數調用到接近錯誤點的位置,然後查看結果。如果可能的話,保護這些調用,以便只有在設置了調試標誌時纔會調用它們。

0

事實證明,我遇到的問題是由於該列表有幾千個元素 - 它應該只有幾十個元素,最大值。

在這個特定的STL實現中,prev指針存儲在每個節點的偏移量0處,所以我可以通過反覆取消引用來跟蹤鏈接。下面的怪物看上去向後20個鏈接:

********************((Metrowerks::node_base**********************)instances->__list_imp.__list_deleter.end_.compressed_pair_imp.second_) 

繼前向鏈路甚至是醜陋的,因爲你必須每次提領後4個字節來抵消。