每个文件启用范围保护

时间:2009-11-18 02:55:59

标签: c++

这是我一直在考虑的一个小问题,因为我还没有找到解决方案。

所以,首先,我有这个用于调试目的的功能保护:

class FuncGuard
{
public: 
    FuncGuard(const TCHAR* funcsig, const TCHAR* funcname, const TCHAR* file, int line);
    ~FuncGuard();
// ...
};

#ifdef _DEBUG
    #define func_guard() FuncGuard __func_guard__( TEXT(__FUNCSIG__), TEXT(__FUNCTION__), TEXT(__FILE__), __LINE__)
#else
    #define func_guard() void(0)
#endif

防护旨在通过将一些信息打印到调试控制台来帮助跟踪代码在运行时所采用的路径。它的用途如下:

void TestGuardFuncWithCommentOne()
{
    func_guard();
}

void TestGuardFuncWithCommentTwo()
{
    func_guard();
    // ...
    TestGuardFuncWithCommentOne();
}

结果就是这样:

..\tests\testDebug.cpp(121):
Entering[ void __cdecl TestGuardFuncWithCommentTwo(void) ]
    ..\tests\testDebug.cpp(114):
    Entering[ void __cdecl TestGuardFuncWithCommentOne(void) ]
    Leaving[ TestGuardFuncWithCommentOne ]
Leaving[ TestGuardFuncWithCommentTwo ]

现在,我很快意识到的一件事是,添加和删除函数调用中的警卫是一件痛苦的事。将它们永久保留在那里也是不可想象的,因为它没有充分的理由消耗CPU周期,并且它可以快速地使应用程序爬行。此外,即使在调试中对应用程序的性能没有影响,调试控制台中很快就会出现大量信息,导致使用此调试工具无效。

所以,我认为在每个文件的基础上启用和禁用它们是个好主意。

这个想法是默认禁用所有功能保护,但只需添加一行,例如

,就可以在整个文件中自动启用它们。
EnableFuncGuards();

位于文件顶部。

我为此考虑了许多解决方案。我不会在这里详细介绍,因为我的问题已经足够长了,但是我只想说我尝试了多个涉及宏的技巧,这些都失败了,一个涉及模板的显式实现,但到目前为止,没有一个可以得到我正在寻找的实际结果。

要注意的另一个限制因素:当前实现功能保护机制的标头包含在预编译的标头中。我知道这会让事情变得复杂,但是如果有人能想出一个可以在这种情况下起作用的解决方案,那就太棒了。如果没有,那么,我当然可以从预编译的头文件中提取该标头。

提前感谢一大堆!

2 个答案:

答案 0 :(得分:2)

向FuncGuard添加一个bool,控制它是否应显示任何内容。

#ifdef NDEBUG
  #define SCOPE_TRACE(CAT)
#else
  extern bool const func_guard_alloc;
  extern bool const func_guard_other;
  #define SCOPE_TRACE(CAT) \
    NppDebug::FuncGuard npp_func_guard_##__LINE__( \
      TEXT(__FUNCSIG__), TEXT(__FUNCTION__), TEXT(__FILE__), \
      __LINE__, func_guard_##CAT)
#endif

实施档案:

void example_alloc() {
  SCOPE_TRACE(alloc);
}
void other_example() {
  SCOPE_TRACE(other);
}

此:

  • 使用特定类别(如果您愿意,每个文件包含一个)
  • 允许在一个函数中使用多个,每个类别或逻辑范围一个(通过在变量名中包含行号)
  • 在NDEBUG版本中编译为空(NDEBUG是标准的非调试宏)

您需要一个项目范围的文件,其中包含您的类别bool的定义,更改此“设置”文件不需要重新编译您的任何其他程序(只是链接),因此您可以get back to work。 (这意味着它对预编译头文件也可以正常工作。)

进一步改进涉及告诉FuncGuard类别,因此它甚至可以登录到多个位置。玩得开心!

答案 1 :(得分:1)

您可以执行与assert()宏类似的内容,其中定义了一些宏或不更改assert()NDEBUG的情况下assert())的定义。< / p>

类似以下内容(未经测试):

#undef func_guard
#ifdef USE_FUNC_GUARD
 #define func_guard() NppDebug::FuncGuard __npp_func_guard__( TEXT(__FUNCSIG__), TEXT(__FUNCTION__), TEXT(__FILE__), __LINE__)
#else
 #define func_guard() void(0)
#endif

要记住的一件事是,执行此操作的包含文件不能包含保护宏(至少不包括此部分)。

然后您可以像这样使用它来控制甚至在编译单元内的跟踪:

#define USE_FUNC_GUARD
#include "funcguard.h"

// stuff you want traced

#undef USE_FUNC_GUARD
#include "funcguard.h"

// and stuff you don't want traced

当然,使用预编译的头文件并不能很好地发挥100%的效果,但我认为在预编译的内容之后的后续包含头文件仍能正常工作。即便如此,这可能是不应该在预编译的标头集中的那种东西。