我正在寻找一种能够以嵌套方式检测有序函数调用对的工具,如下所示:
f() // depth 0
f() //depth 1
g()
g()
在每个呼叫深度f()
,必须有g()
调用形成函数呼叫对。这在关键部分进入和退出时尤其重要。
答案 0 :(得分:11)
在C ++中,一个选项是在类的构造函数和析构函数中包含对f()
和g()
的调用,并且只通过实例化该类的实例来调用这些函数。例如,
struct FAndGCaller
{
FAndGCaller() { f(); }
~FAndGCaller() { g(); }
};
然后可以在任何范围块中使用它,如下所示:
{
FAndGCaller call_f_then_later_g; // calls f()
} // calls g()
显然,在实际代码中,您需要更恰当地命名,并且通常只需要在构造函数和析构函数体中包含f()
和g()
的内容,而不是单独的职能。
范围界限资源管理(SBRM,或更常见的资源获取是初始化,RAII)的这种习惯用法非常普遍。
答案 1 :(得分:2)
您可能会滥用for
- 循环。
#define SAVETHEDAY for (bool seen = ((void)f(), true); seen; seen = ((void)g(), false))
逗号运算符始终让您的函数f
在依赖语句之前执行,之后执行g
。 E.g
SAVETHEDAY {
SAVETHEDAY {
}
}
优点:
for
- 循环将是
任何体面的优化
编译器。缺点:
break
,return
和continue
在块内部,因此在这种情况下可能不会调用g
。throw
内,再次g
可能不会被称为 continue
的问题可以通过更巧妙地处理来修复。
通过使用伪类型for
- 在构造函数和析构函数中只有f
和g
的变量,可以在C ++中规避前两个缺点。
答案 2 :(得分:0)
扫描代码(这是困难的部分),每次看到f()
的调用时,都会增加一个计数器。每次看到g()
的调用时,都会递减计数器。最后,计数器应该回零。如果它变为负数,那么这也是一个问题(您呼叫g()
之前没有匹配调用f()
)。
准确地扫描代码是困难的部分 - 使用C和(特别是)C ++,编写代码来理解源代码非常困难。另外,我不知道这个特定工作的现有工具。你可以毫无疑问地得到clang(举一个例子)去做,虽然它比完全靠你自己做的容易得多,但它仍然不会是微不足道的。
答案 3 :(得分:0)
用于语义搜索和修补C代码的Coccinelle工具专为此类任务而设计(另请参阅工具上的this LWN article)。