2010-01-14 24 views
1

我正在尋找如何通過向我的應用程序添加代碼來幫助調試的提示。一個例子,以便它變得更加清晰:爲了檢測由shared_ptrs持有的懸掛對象,我創建了一個跟蹤器類,使我可以跟蹤多少個對象處於活動狀態以及最初創建的位置,這是然後這樣使用:編碼便於調試

class MyClass { 
    TRACK_THIS_TYPE(MyClass); 
}; 

boost::shared_ptr<MyClass> myObj(new MyClass); 
TRACK_THIS_OBJECT(myObj); 

其中TRACK_THIS_TYPE(t)是一個宏,可以確保我得到(有多少對象已經被創建和計數)的實例計數爲一類和TRACK_THIS_OBJECT是一個宏店該對象創建的文件和行以及weak_ptr與該對象一起使用。

這使我可以檢測懸掛對象以及它們在哪裏創建。它不允許我找出哪些對象將shared_ptr保存到我的對象,這可能是對上述的改進。我想可以創建一個類似於TRACK_THIS_PTR(T)的宏來存儲文件和行,以創建shared_ptr實例。

另一個例子是舊

assert(condition && "My descriptive text"); 

,可以讓你直接把有意義的評論到斷言。

有沒有人有收集統計​​數據,自動堆棧跟蹤,跟蹤對象/指針/資源,死鎖/飢餓或其他線程問題檢測,確保異常處理某處,文檔幫助或類似的任何整潔的C++技巧?任何事情都是真的,無論是有助於防止錯誤的東西,還是事後有所幫助的東西。

編輯:除了對此問題的回覆外,我還收到有關google-glog作爲日誌記錄實用程序的提示。

+0

小心與斷言和副作用!它可以在部署/調試時更改您的行爲(假定您爲部署時間構建刪除了斷言)。 – 2010-01-14 13:11:01

+0

你可以舉一個副作用的例子嗎? – 2010-01-14 13:14:32

+1

這是一篇關於編寫Assert宏的大文章,並且可能是一般的宏.. http://cnicholson.net/2009/02/stupid-c-tr​​icks-adventures-in-assert/ – 2010-01-14 14:05:02

回答

2

以下主要是爲了便於調試之後的發佈。

Stackwalker和類似的工具提供了一種簡單的方法來在最終用戶機器上獲得可用的調用堆棧,而沒有調試器處於活動狀態。相似地,Google Breakpad可以用來輕鬆從崩潰的進程中提取小型轉儲。

+0

我之前並不瞭解Google Breakpad。我認爲它看起來非常有趣,並且可能是從「野外」潛在崩潰中獲取信息的一種非常好的方式。 – villintehaspam 2010-01-15 22:09:04

+0

接受了這個答案,因爲我現在已經開始使用Breakpad,效果很好。 – villintehaspam 2011-02-09 14:33:43

1

你可以看看記錄你的東西,如「log4cxx」生產統計

http://logging.apache.org/log4cxx/index.html

這應該讓你控制跟蹤你在運行時通過配置至少做(或水平文件在運行時讀入)。

它會自動爲您的日誌記錄添加時間戳,並讓您設置輸出格式以適應其他工具(如Excel或數據庫),以便您對日誌數據進行統計分析。

4

我使用BOOST_ASSERT很多,檢查輸入,中間計算和返回之前,即使它看起來很明顯。

它強制你考慮什麼樣的值可以把你的數據,並可以更容易迅速找到一個重構,留下一些愚蠢的錯誤。

如果您真的關注性能,可以爲發佈版本禁用它們。

關於內存管理,我大量使用RAII,儘量儘量少用指針和手動內存分配。在代碼中只有2或3個指針時,避免發生錯誤會更容易。

1

我個人更喜歡瞄準沒有寫錯誤的地方。將調試代碼添加到應用程序可能會產生不幸的副作用。它顯然會影響性能,並且在多線程應用程序的情況下,可能會改變應用程序的時間,導致隱藏MT錯誤。

我發現我通常花很少時間調試我的代碼 - 任何時候我花在調試器上的時間都是浪費時間。我發現確實有幫助的是在每次更改後都可以運行測試 - 您不必接受TDD使用此方法。

+1

我想我們大多數人旨在不寫bug ... :)影響性能是好的,通常任何這樣的調試代碼只包含在調試版本中。你有關測試的觀點是非常有效的。 您還有一個有效的觀點,即調試代碼可能會影響程序的行爲 - 這並不意味着包含調試代碼(用於調試構建)始終是一件壞事。 – villintehaspam 2010-01-14 13:20:07

+2

我認爲你不會做太多的MT工作?說真的,我已經看到了即使寫一個簡單的調試日誌隱藏MT錯誤的情況。 – 2010-01-14 13:21:53

+0

@Neil Butterworth:我做了很多多線程編碼,是的,我已經看到了調試代碼影響計時的情況,例如寫入日誌或其他東西時。還有很多其他事情會影響時序 - 即使沒有自己的調試代碼,調試和發佈版本的行爲也會有很大不同。您通常應該能夠使用定義或類似語句來包含/排除調試代碼,以便您可以在調試版本和發佈版本的測試中使用或不使用它。 – villintehaspam 2010-01-14 13:27:16

3

有趣的是,我們在工作中有一個相當類似的項目來跟蹤內存問題。

許多人發誓RAII,但即使使用shared_ptr您可以創建泄漏,由於引用週期的問題是主要(這就是爲什麼引用計數基於垃圾收集器有特殊算法來檢測週期):X

公司我爲(艾瑪迪斯)工作,目前正在開發AMPolice,其中重新編號爲valgrind。它仍在進行中,特別是在文件部門。如你所見,這與你自己的方法完全不同:二進制保持不變,並且在必要時通過切換到「調試」存儲器管理(在運行時)來跟蹤存儲器分配(使用命令 - 在線API)。

因此,使用起來更容易,雖然從我們的測試中確實會影響計時(4x或5x)。

該工具是非常通用的,所以通常會被很多人使用,當然最主要的問題仍然是,因爲跟蹤每一個new日誌的剪切大小是相當昂貴:X

0

我的C++是有點現在生疏,但我記得,每當我不得不分配一個對象我有這樣的執行它像宏:

NEW(類)

,然後叫釋放對象的釋放宏。然後每個宏將存儲對象創建和銷燬的類和行號。

這將允許通過查看未釋放對象的位置來輕鬆檢測內存泄漏。