Documentation Project 1
ContentsIndexHome
PreviousUpNext
sack::DBG_PASS Macro
C++
#define DBG_PASS 

in NDEBUG mode, pass nothing. 

 

This function allows specification of DBG_RELAY or DBG_SRC under debug compilation. Otherwise, the simple AddLink macro should be used. DBG_RELAY can be used to forward file and line information which has been passed via DBG_PASS declaration in the function parameters. 

 

This is a part of a set of macros which allow additional logging information to be passed. 

 

These 3 are the most commonly used. 

 

DBG_SRC - this passes the current __FILE__, __LINE__ parameters. 

DBG_PASS - this is used on a function declaration, is a filename and line number from DBG_SRC or DBG_RELAY

DBG_RELAY - this passes the file and line passed to this function to another function with DBG_PASS defined on it. 

 

DBG_VOIDPASS - used when the argument list is ( void ) without debugging information. 

DBG_VOIDSRC - used to call a function who's argument list is ( void ) without debugging information. 

DBG_VOIDRELAY - pass file and line information forward to another function, who's argument list is ( void ) without debugging information. 

The SACK library is highly instrumented with this sort of information. Very commonly the only difference between a specific function called 'MyFunctionName' and 'MyFunctionNameEx' is the addition of debug information tracking. 

 

The following code blocks show the evolution added to add instrumentation... 

 

int MyFunction( int param )
{
    // do stuff
}
   
int CallingFunction( void )
{
    return MyFunction();
}

 

Pretty simple code, a function that takes a parameter, and a function that calls it. 

The first thing is to extend the called function.

int MyFunctionEx( int param DBG_PASS )
{
    // do stuff
}

 

And provide a macro for everyone else calling the function to automatically pass their file and line information

#define MyFunction(param)  MyFunctionEx(param DBG_SRC)

 

Then all-together

#define MyFunction(param)  MyFunctionEx(param DBG_SRC)
   
int MyFunctionEx( int param DBG_PASS )
{
    // do stuff
}
   
   
int CallingFunction( void )
{
    // and this person calling doesn't matter
    // does require a recompile of source.
    return MyFunction( 3 );
}
   

 

But then... what if CallingFunction decided wasn't really the one at fault, or responsible for the allocation, or other issue being tracked, then she could be extended....

int CallingFunctionEx( DBG_VOIDPASS )
#define CallingFunction() CallingFunction( DBG_VOIDSRC )
{
    // and this person calling doesn't matter
    // does require a recompile of source.
    return MyFunction( 1 DBG_RELAY );
}

 

Now, calling function will pass it's callers information to MyFunction.... 

 

Why? 

 

Now, when you call CreateList, your code callng the list creation method is marked as the one who allocates the space. Or on a DeleteList, rather than some internal library code being blamed, the actual culprit can be tracked and identified, because it's surely not the fault of CreateList that the reference to the memory for the list wasn't managed correctly.

It is important to note, every usage of these macros does not have a ',' before them. This allows non-debug code to eliminate these extra parameters cleanly. If the ',' was outside of the macro, then it would remain on the line, and an extra parameter would have be be passed that was unused. This is also why DBG_VOIDPASS exists, because in release mode this is substituted with 'void'. 

 

In Release mode, DBG_VOIDRELAY becomes nothing, but when in debug mode, DBG_RELAY has a ',' in the macro, so without a paramter f( DBG_RELAY ) would fail; on expansion this would be f( , pFile, nLine ); (note the extra comma, with no parameter would be a syntax error.

This example shows forwarding debug information through a chain of routines.

void ReportFunction( int sum DBG_PASS )
{
    printf( "%s(%d):started this whole mess\n" DBG_RELAY );
}
   
void TrackingFunction( int a, int b DBG_PASS )
{
    ReportFunction( a+b, DBG_RELAY );
}
   
void CallTrack( void )
{
    TrackingFunction( 1, 2 DBG_SRC );
}

 

In this example, the debug information is passed to the logging system. This allows logging to blame the user application for allocations, releases, locks, etc...

void MyAlloc( int size DBG_PASS )
{
    _lprintf( DBG_RELAY )( ": alloc %d\n", size );
}
void g( void )
{
    lprintf( "Will Allocate %d\n", 32 );
    MyAlloc( 32 DBG_SRC );
}
   

 

This example uses the void argument macros

   
void SimpleFunction( DBG_VOIDPASS )
{
    // this function usually has (void) parameters.
}
   
void f( void )
{
    SimpleFunction( DBG_VOIDSRC );
}
Copyright (c) 2010. All rights reserved.
What do you think about this topic? Send feedback!