我期待能夠檢測以嵌套的方式有序函數調用對的工具,如下圖所示:如何檢測正確的函數調用對
f() // depth 0
f() //depth 1
g()
g()
在通話f()
的每個深度必須有g()
通話形成函數調用對。這在臨界區進入和退出時尤爲重要。
我期待能夠檢測以嵌套的方式有序函數調用對的工具,如下圖所示:如何檢測正確的函數調用對
f() // depth 0
f() //depth 1
g()
g()
在通話f()
的每個深度必須有g()
通話形成函數調用對。這在臨界區進入和退出時尤爲重要。
在C++中,一個選項是將調用包裝到f()
和g()
的類的構造函數和析構函數中,並通過實例化該類的實例來調用這些函數。例如,
struct FAndGCaller
{
FAndGCaller() { f(); }
~FAndGCaller() { g(); }
};
然後可以在任何範圍內塊中使用,像這樣:
{
FAndGCaller call_f_then_later_g; // calls f()
} // calls g()
很顯然,在實際的代碼,你會希望更適當命名的東西,而且通常會只是想在構造函數和析構函數體中具有f()
和g()
的內容,而不是在單獨的函數中。
這個範圍綁定資源管理(SBRM,或更常被稱爲資源獲取是初始化,RAII)的習慣用法很常見。
如果f()拋出一個錯誤,g()永遠不會被調用,但是類/結構的資源將被釋放。 – 2010-08-14 12:14:28
@ PC2st:是的,但如果'g()'做與f()'做相反的操作(或「撤銷」),那麼如果'f()'拋出一個你不想調用的異常'g ()'。 – 2010-08-14 13:30:02
掃描代碼(這是困難的部分),每次看到f()
的調用時,都會增加一個計數器。每次看到g()
的調用時,都會減少計數器。最後,計數器應該回到零。如果它發生負面情況,那也是一個問題(你有一個g()
的電話,並且之前沒有與f()
匹配的電話)。
準確地掃描代碼雖然很難 - 用C和(特別是)C++編寫代碼來理解源代碼很難極其。不客氣,我不知道這個特定工作的現有工具。毫無疑問,你可以讓叮噹(舉一個例子)來做,但是它比完全依靠自己做起來要容易得多,但它仍然不是微不足道的。
這種方法的問題是它不檢查f()和g()的級別 - 它會確保你有合適的數量,但它不能保證你讓他們在同一層次上彼此鏡像。此外,OP要求使用工具,而不是查看代碼的方式。 – 2010-08-13 21:07:59
@adam_0:至少根據他顯示的代碼,通過調用f()和g()來定義級別。如果還有更多的情況,他可能需要告訴我們要得到一個有意義的答案是什麼。我懷疑現在有什麼工具可以完全滿足他的要求,所以我試圖告訴他如何構建一個。 – 2010-08-13 21:11:41
除clang之外的另一種選擇是使用Qt-Creator附帶的諾基亞C++解析器庫。它是跨平臺的,自包含的(libCPlusPlus。{so,dll}),並且不難開始,但它仍然不是微不足道的。這本書寫得很好,得到很好的支持,因爲它已經用於他們的許多不同項目。 – 2010-08-13 21:11:50
爲此,您可能會濫用for
-loop。
#define SAVETHEDAY for (bool seen = ((void)f(), true); seen; seen = ((void)g(), false))
逗號操作符總是讓你的功能f
可以在相關的語句之前和之後g
執行。 E.g
SAVETHEDAY {
SAVETHEDAY {
}
}
優點:
for
-loop將由 編譯器優化掉 。缺點:
break
,return
和continue
塊裏面,所以g
可能無法在這種情況下調用。throw
內部安全,再次g
可能不叫與continue
問題可以通過一個更加聰明的做事修復。 前兩個cons可以通過在構造函數和析構函數中使用和g
作爲for
-變量的虛擬類型在C++中繞過。
用於C代碼語義搜索和修補的Coccinelle工具專爲此類任務而設計(另請參見工具上的this LWN article)。
在從'f'返回之前,爲什麼不從'f'調用'g'? – Chubsdad 2010-08-14 01:12:21
@chubsdad:因爲'f()'和'g()'之間存在代碼,所以可能認爲是'lock()'和'unlock()',而不是'f()'和'g()'。 – caf 2010-08-14 07:32:14