开发者

Per-file enabling of scope guards

Here's a little problem I've been thinking about for a while now that I have not found a solution for yet.

So, to start with, I have this function guard that I use for debugging purpose:

class FuncGuard
{
public: 
    FuncGuard(const TCHAR* funcsig, const T开发者_如何学JAVACHAR* 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

The guard is intended to help trace the path the code takes at runtime by printing some information to the debug console. It is intended to be used such as:

void TestGuardFuncWithCommentOne()
{
    func_guard();
}

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

And it gives this as a result:

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

Now, one thing that I quickly realized is that it's a pain to add and remove the guards from the function calls. It's also unthinkable to leave them there permanently as they are because it drains CPU cycles for no good reasons and it can quickly bring the app to a crawl. Also, even if there were no impacts on the performances of the app in debug, there would soon be a flood of information in the debug console that would render the use of this debug tool useless.

So, I thought it could be a good idea to enable and disable them on a per-file basis.

The idea would be to have all the function guards disabled by default, but they could be enabled automagically in a whole file simply by adding a line such as

EnableFuncGuards();

at the top of the file.

I've thought about many a solutions for this. I won't go into details here since my question is already long enough, but let just say that I've tried more than a few trick involving macros that all failed, and one involving explicit implementation of templates but so far, none of them can get me the actual result I'm looking for.

Another restricting factor to note: The header in which the function guard mechanism is currently implemented is included through a precompiled header. I know it complicates things, but if someone could come up with a solution that could work in this situation, that would be awesome. If not, well, I certainly can extract that header fro the precompiled header.

Thanks a bunch in advance!


Add a bool to FuncGuard that controls whether it should display anything.

#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

Implementation file:

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

This:

  • uses specific categories (including one per file if you like)
  • allows multiple uses in one function, one per category or logical scope (by including the line number in the variable name)
  • compiles away to nothing in NDEBUG builds (NDEBUG is the standard I'm-not-debugging macro)

You will need a single project-wide file containing definitions of your category bools, changing this 'settings' file does not require recompiling any of the rest of your program (just linking), so you can get back to work. (Which means it will also work just fine with precompiled headers.)

Further improvement involves telling the FuncGuard about the category, so it can even log to multiple locations. Have fun!


You could do something similar to the assert() macro where having some macro defined or not changes the definition of assert() (NDEBUG in assert()'s case).

Something like the following (untested):

#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

One thing to remember is that the include file that does this can't have include guard macros (at least not around this part).

Then you can use it like so to get tracing controlled even within a compilation unit:

#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

Of course this doesn't play 100% well with pre-compiled headers, but I think that subsequent includes of the header after the pre-compiled stuff will still work correctly. Even so, this is probably the kind of thing that shouldn't be in a pre-compiled header set.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜