Thread: using macros for multilevel debug

  1. #1
    Registered User zolfaghar's Avatar
    Join Date
    Mar 2016
    Posts
    95

    using macros for multilevel debug

    Hi
    I am following a text, and in it, the author suggests implementing multi level debug messages with a macro definition so you can execute the program as follows:

    Code:
    a.out -d3
    And it would provide a more verbose level of debug as opposed to level 1. He says I can put the following code in a header file

    Code:
    #ifdef DEBON
    #define DEBUG(level,fmt, ...)        if (Debug >= level) fprintf (stderr, fmt, __VA_ARGS__)
    #else
    #    define DEBUG(level, fmt, ...)
    #endif
    I just put the code in my sample program as follows:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    // int Debug;
    //#define DEBUG(fmt, ...)  fprintf (stderr, fmt, __VA_ARGS__ )
    #ifdef DEBON
    #define DEBUG(level,fmt, ...)        if (Debug >= level) fprintf (stderr, fmt, __VA_ARGS__)
    #else
    #    define DEBUG(level, fmt, ...)
    #endif
    int process ( int i1, int i2)
    {
      int val;
      DEBUG (1, "process (%i, %i)\n", i1, i2);
      val = i1 * i2;
      DEBUG (3, "return %i\n", val);
      return val;
    }
    int main ( int argc, char *argv[])
    {
    int arg1 = 0, arg2 = 0;
    if (argc > 1)
    arg1 = atoi (argv[1]);
    if ( argc == 3)
      arg2 = atoi (argv[2]);
    DEBUG (1, "processed %i arguments\n", argc -1 );
    DEBUG (3, "arg1 = %i, arg2 = %i\n" , arg1, arg2);
    printf ("%d\n", process (arg1, arg2));
    return 0;
    }
    But I get the following error messages:

    Code:
    $ gcc -g -D DEBON 173.c -o 173
    173.c: In function 'process':
    173.c:6:39: error: expected expression before 'if'
     #define DEBUG(level,fmt, ...)        (if (Debug >= level) fprintf (stderr, fmt, __VA_ARGS__))
                                           ^
    173.c:14:3: note: in expansion of macro 'DEBUG'
       DEBUG (1, "process (%i, %i)\n", i1, i2);
       ^
    173.c:6:39: error: expected expression before 'if'
     #define DEBUG(level,fmt, ...)        (if (Debug >= level) fprintf (stderr, fmt, __VA_ARGS__))
                                           ^
    173.c:16:3: note: in expansion of macro 'DEBUG'
       DEBUG (3, "return %i\n", val);
       ^
    173.c: In function 'main':
    173.c:6:39: error: expected expression before 'if'
     #define DEBUG(level,fmt, ...)        (if (Debug >= level) fprintf (stderr, fmt, __VA_ARGS__))
                                           ^
    173.c:27:1: note: in expansion of macro 'DEBUG'
     DEBUG (1, "processed %i arguments\n", argc -1 );
     ^
    173.c:6:39: error: expected expression before 'if'
     #define DEBUG(level,fmt, ...)        (if (Debug >= level) fprintf (stderr, fmt, __VA_ARGS__))
                                           ^
    173.c:28:1: note: in expansion of macro 'DEBUG'
     DEBUG (3, "arg1 = %i, arg2 = %i\n" , arg1, arg2);
     ^
    I have seen some similar posts about this. One of them was Good practice of writing debug print statements
    But I can not quite follow the advice. What am I doing wrong?

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I probably shouldn't show you this, but this is how your macros expanded....
    Code:
    gcc -g -D DEBON -E debug.c
    < whiteflags snipped unhelpful preprocessor code >
    
    if (Debug >= 1) fprintf ((&_iob[2]), "processed %i arguments\n", argc -1);
    if (Debug >= 3) fprintf ((&_iob[2]), "arg1 = %i, arg2 = %i\n", arg1, arg2);
    
    < code continues >
    Now, other than you seeing the guts of stdout, we can also see that the code depends on Debug, a variable you commented out.

    The C compiler removes comments before it expands macros.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    By the way, your way (or the author's way) of implementing the macro can be problematic. Consider:
    Code:
    if (whatever)
        foo();
        DEBUG(1, "test #%d", 1);
    else
        bar();
    At a glance, it looks like there should be a compile error since the else does not match the if as braces were not used to combine the two statements into a single block of code forming the body of the if statement. However, the code may well compile because if DEBON is defined, after preprocessing it would look something like:
    Code:
    if (whatever)
        foo();
        if (Debug >= level)
            fprintf(stderr, "test #%d", 1);
    else
        bar();
    or with braces:
    Code:
    if (whatever)
    {
        foo();
    }
    if (Debug >= level)
    {
        fprintf(stderr, "test #%d", 1);
    }
    else
    {
        bar();
    }
    One way to fix this is to enclose the implementation of the function-style macro in a do while (0) block, e.g.,
    Code:
    #define DEBUG(level, fmt, ...) do {\
        if (Debug >= level)\
            fprintf(stderr, fmt, __VA_ARGS__);\
    } while (0)
    Personally, instead of both an int global variable named Debug and a macro named DEBON, I wonder it would be simpler to have a macro named DEBUG_LEVEL that is left undefined if these debugging outputs are to be disabled, and defined to an integer if they are to be enabled. You would then also define named constants (maybe using an enum) for your debugging levels instead of using magic numbers like 1 and 3 (ideas on such names are all over various programming languages, libraries, frameworks, etc, that can be found on the Internet, though the more commonly used term is "logging" whereas debugging is more of an activity that might make use of logs).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    You could also give up and use a debugger. I find RMS's gdb Tutorial to be a gentle introduction to them, since even if you don't use GDB, the features that GDB provides and the way the tutorial exposes them to the reader echo real world uses of other debuggers that other IDEs come bundled with.
    Last edited by whiteflags; 06-22-2016 at 11:05 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What different in macros?
    By dpp in forum C++ Programming
    Replies: 8
    Last Post: 12-11-2009, 11:35 AM
  2. Macros inside of macros
    By Chewie8 in forum C Programming
    Replies: 2
    Last Post: 02-24-2008, 03:51 AM
  3. Multilevel Inheritance
    By duvernais28 in forum C++ Programming
    Replies: 3
    Last Post: 03-13-2006, 05:57 PM
  4. macros
    By Chaplin27 in forum C++ Programming
    Replies: 7
    Last Post: 03-02-2005, 01:06 PM
  5. Min and Max Macros
    By Batman.......hehehehe in forum C++ Programming
    Replies: 2
    Last Post: 07-09-2002, 01:14 PM

Tags for this Thread