我目前正在将分析系统实现到应用程序中。
我有两个基于编译器标志 (NDEBUG) 定义的宏函数。当未定义 NDEBUG 时,这两个函数 (profilingStart/profilingEnd) 生成分析报告,显示调用 profilingStart 的时间与调用 profilingEnd 的时间。
问题是可能会发生不匹配——即调用 profilingStart 而未调用 profilingEnd 的情况(反之亦然)。我的代码已经在运行时识别出这些情况,但如果由于这种不匹配而在编译时导致错误,那将是更可取的。
一个建议是使用 do{...}while();构造以确保分析功能正确配对。开始宏函数将包含 do{,结束宏将包含 }while()。如果缺少一个,我们会在编译时出错。但是,这有一些问题——您只能在正在分析的函数的开头和结尾使用 profilingStart() 和 profilingEnd() 调用,因为在函数内使用它们可能会影响局部变量的范围(因为它们可能会由于 do{...}while() 调用而超出范围)。
我的另一个想法是在 profilingStart 函数中声明一个变量,然后尝试在 profilingEnd 函数中修改该变量的内容。这可以防止范围问题,如果变量从未声明过,则会产生编译器错误。但是,我永远不会有任何方法来验证变量的内容是否在 end 函数中被修改。这只能帮助解决一半的问题,因为它不会验证 profilingEnd 函数的调用。
一如既往地欢迎任何意见。提前致谢。
编辑:我对范围的评论可能有些困惑。 profilingStart() 和 profilingEnd() 将始终在同一个函数中调用。它们可能不会在函数的最开始/最结束时被调用。这是我的意思的一个例子:
int DoSomething(void)
{
profilingStart();
int a;
DoMath(a);
profilingStop();
return a; // a is out of scope here, as the do{...}while(0) construct has gone out of scope
}
最佳答案
在 C++ 中,一种解决方案是使用“RAII”习惯用法。像这样:
class Profiler {
public:
Profiler() { profilingStart(); }
~Profiler() { profilingEnd(); }
}
然后你像这样使用它:
{ // start of block you want to profile
Profiler prof;
...
}
这将确保 profilingEnd
即使在出现异常、提前返回、break
等情况下也会被调用。也就是说,它绝对保证调用是成对的。
不过,它确实需要将您想要分析的代码放在一个 block 中。
[编辑]
我没有注意到您希望能够将 profilingEnd
放在与 profilingStart
不同的 block 中。
有关如何处理此问题的想法,请参阅下面@Roddy 的评论;例如通过让析构函数检查以确保分析器在对象被析构时已经停止。虽然这不会在编译时发现问题,但会在运行时“接近”问题。
关于c++ - 匹配开始/结束分析调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6601874/