C debugging macro (with various debugging "sources")

I decided to make myself a neat C debugging macro, not quite sure what I really wanted (and, being ignorant when it comes to macros), I turned to Google. Some time later, and now I think I know what I want, but not how it works. I was not very lucky to get decent information about macros and debugging methods.

What I used in the past was something like this:

#ifdef DEBUG #define DBG(x) printf x #else #define DBG(x) /* nothing */ #endif 

The problem is that it can become quite confusing, and eventually you end up commenting on old debugging messages, although they will probably need you later.

The best example I've found is some slides from the advanced c course, which can be found here: http://www.mpi-inf.mpg.de/departments/rg1/teaching/advancedc-ws08/script/lecture07.pdf (the corresponding parts are slide 19-23, but most of them are given below)

Being lecture slides, they, unfortunately, need some explanation. But they mention something that seems quite useful:

 DBG((MOD_PARSER , "z = %d\n", z)); 

Where MOD_PARSER is the debugging module / category, and the rest of the arguments are for printing. A.

And the DBG implementation:

 #ifdef PRGDEBUG #define DBG(x) dbg_printer x #else #define DBG(x) /* nothing */ #endif void dbg_printer(int module , const char *fmt, ...); 

Problem # 1 is writing the dbg_printer function, I'm not sure how to pass a variable number of arguments to the printf statement.

The slides discuss how to gracefully add new modules, and I'm sure I didn't understand that at all, but anyway ...

 *How to add new modules elegantly *Add a file debug_modules.def ADD_MOD(0, PARSER) ADD_MOD(1, SOLVER) ADD_MOD(2, PRINTER) 

...

 *"Generate" an enum with debug modules: debug.h ... #define ADD_MOD(num, id) MOD_ ## id = 1 << num, enum _debug_modules_t { #include "debug_modules.def" }; #undef ADD_MOD ... 

...

 *Preprocessor yields enum _debug_modules_t { MOD_PARSER = 1 << 0, MOD_SOLVER = 1 << 1, MOD_PRINTER = 1 << 2, }; 

I don’t understand why you would leave a shift in the values ​​of the enumeration elements, some graceful trick that I am missing?

Apart from the slides above, I have not seen a single example, no article / message, or even mention of it, so maybe this is not even suitable for my purposes. Does this sound reasonable and are similar methods used?

At the moment, the question is how to implement dbg_printer and really, how the numbering of debug modules should work, but seeing how I could misunderstand everything that could change :(

+4
source share
2 answers

To pass a variable number of arguments from dbg_printer , you call vfprintf instead of fprintf . Something like that:

 #include <stdarg.h> extern int dbg_mod_stderr; extern int dbg_mod_file; extern FILE *dbg_file; void dbg_printer(int module , const char *fmt, ...) { if (dbg_mod_stderr & module) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } if (dbg_file != NULL && (dbg_mod_file & module)) { va_list ap; va_start(ap, fmt); vfprintf(dbg_file, fmt, ap); va_end(ap); } } 

(This example shows how to allow one set of debug messages to go to stderr and another set to the debug file)

The left shift of constants allows you to select any subset of modules, and not just one. For example, with the code above, you would enable debugging of the analyzer and solver on stderr as follows:

 dbg_mod_stderr |= MOD_PARSER; dbg_mod_stderr |= MOD_SOLVER; 

and you could subsequently disable solver debugging as follows:

 dbg_mod_stderr &= ~MOD_SOLVER; 

(This works because each MOD_ constant has only one unique bit set in binary representation).

+2
source

I don’t understand why you would leave a shift in the values ​​of the enumeration elements, some great trick I miss?

This is most likely the case that more than one of the elements can be specified by combining them with bitwise or.

My preferred debug macro has no module specifics, but it adds the file name and line number to the output and is relatively simple:

  #ifdef DEBUG #define DLOG(fmt, args...) printf("%s:%d "fmt,__FILE__,__LINE__,args) #else #define DLOG(fmt, args...) #endif 

edit: This is more like what I'm using now, based on the comments below ( __PRETTY_FUNCTION__ and ##__VA_ARGS__ ) and this Q & A ( do {} while (0) ):

  #ifdef DEBUG #define DLOG(fmt, ...) printf("%s:%d "fmt, __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define DLOG(fmt, ...) do {} while (0) #endif 
+6
source

Source: https://habr.com/ru/post/1303865/


All Articles