Programs in C that have --verbose or --debug option, how they actually implement it? Without using 3rd party libraries.
My goal is not to do this all the time:
if(debug) printf("Debug msg\n");
printf("Info msg\n");
The most common I've seen is to print to stderr.
#ifdef DEBUG
#define DEBUG_MESSAGE(fmt, ...) fprintf(stderr, fmt ## "\n", __VA_ARGS__)
#else
#define DEBUG_MESSAGE(fmt, ...)
#endif
Elsewhere...
DEBUG_MESSAGE("VERBOSE: %s", "This is a verbose message.");
EDIT
Something that would work at runtime:
#define DEBUG_MESSAGE(fmt, ...)\
do{\
if(g_debugEnabled) fprintf(stderr, fmt ## "\n", __VA_ARGS__);\
}while(0)
Which can be used similarly.
LAST EDIT
Changed to use arbitrary format string with __VA_ARGS__.
You can refer the below program where a macro is defined and based on the option passed to the executable logging is enabled.
#include <stdio.h>
#include <string.h>
#define STREQ(a, b) !(strcmp((a), (b)))
#define logmsg(fmt, ...) \
do { \
if (debug) \
printf(fmt, ##__VA_ARGS__);\
}while(0)
char debug;
int main(int argc, char *argv[])
{
if (argc > 1) {
if ( STREQ(argv[1], "debug"))
debug = 1;
}
logmsg("%s\n", "hello_world");
return 0;
}
Pass debug as the first argument to the executable to enable logging
Note : This program has been tested on Linux with gcc compiler
Related
I use a LOG_DEBUG function to print debug information to the screen. I used a #define _DEBUG to disable LOG_DEBUG function by defining _DEBUG FLAG in compile time (release time). but linux strings commands of release build app still shows debug strings which exists in the compiled app. so what is the alternatives to eliminate arguments of LOG_DEBUG?
#ifdef _DEBUG
#define LOG_DEBUG(fmt, ...) printf("[D][%s:%d %s]", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#else
#define LOG_DEBUG(fmt, ...)
#endif
LOG_DEBUG("this is a debug string"); // "this is a debug string" exists in app release build yet
the compiler I use: ARM/Thumb C/C++ Compiler, RVCT3.1 [Build 569]
optimization: -O3
You could try using stringification:
#include <stdio.h>
#define _DEBUG
#ifdef _DEBUG
#define LOG_DEBUG(str) do { printf("[D][%s:%d %s] ", \
__FILE__, \
__LINE__, \
__FUNCTION__); \
puts(#str); } while(0)
#else
#define LOG_DEBUG(str)
#endif
int main() {
LOG_DEBUG(this is a debug string);
return 0;
}
Note: I tested this in clang, which doesn't exhibit the behaviour you described.
I want to enable "printf("macro MESSAGE is %d\n",MESSAGE);" during run time. For example , if i give argument 10 in run time, it should print the message. if it is not given, it should not print this message.Is it possible?
#include <stdio.h>
#define MESSAGE 10
int foo;
void main(int argc, char *argv[])
{
foo = atoi(argv[1]);
printf("foo is %d\n", foo);
#if MESSAGE==foo
printf("macro MESSAGE is %d\n",MESSAGE);
#endif
}
We can define a macro conditionally based on a preprocessor macro to control in compile time what the definition of the macro is:
#if DEBUGGING
#define debug(format, ...) fprintf(stderr, format, __VA_ARGS__)
#else
#define debug(format, ...) ()
#endif
The debug macro itself is actually an example in GCC's manual.
Or, we could make a similar function that checks in run time the value of some variable:
#include <stdarg.h>
#include <stdio.h>
int debugging = 10;
void debug(int msglevel, const char *fmt, ...)
{
if (debugging < msglevel) return;
va_list va;
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
}
...
debug(10, "Error: %s\n", "some explanation");
A full function makes it easier to do a greater than comparison for the verbosity level. Of course we could still have an alternate definition of r the function on compile time to fully disable it. For the varargs, see the va_arg(3) man page.
I currently have a bunch of debug macros (hijacked from Zed's book Learn C The Hard Way) and I'm trying to compile them on AIX. The macros:
#ifndef __dbg_h__
#define __dbg_h__
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, s ...)
#else
#define debug(M, s ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ## s)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, s ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ## s)
#define log_warn(M, s ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ## s)
#define log_info(M, s ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ## s)
#define check(A, M, s ...) if(!(A)) { log_err(M, ## s); errno=0; goto error; }
#define sentinel(M, s ...) { log_err(M, ## s); errno=0; goto error; }
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, s ...) if(!(A)) { debug(M, ## s); errno=0; goto error; }
#endif
When I compile my project that imports these macros, the AIX CC compiler prints compiler errors with this message, and then exits normally:
"src/dbg.h", line 13.19: 1506-211 (S) Parameter list must be empty, or consist of one or more identifiers separated by commas.
It prints one of these to every line in the project that use one of the macro functions.
I've tried setting #pragma langlvl (stdc99) and #pragma langlvl (extc99) as advised in this article with no success.
I've also written a small example to see if I can compile it, as follows:
/* file "test.c" */
#include <stdio.h>
#define PRINTERROR(M, s...) fprintf(stderr, "ERROR MSG: " M "\n", ## s)
int main(void) {
PRINTERROR("no args");
PRINTERROR("with args: %s", "foo");
return 0;
}
The compiler emits the following message:
"test.c", line 4.24: 1506-211 (S) Parameter list must be empty, or consist of one or more identifiers separated by commas.
I'm using AIX 5.3 and CC for AIX version 6.0.0.0.
Your code -- either the original version or the edited one, which is using a non-standard extension, see the answer by ouah -- compiles fine for me on AIX 6.1 using XL C/C++ v11.1.
You state that your compiler is CC for AIX version 6.0.0.0. If that is to mean "IBM VisualAge C++ Professional for AIX, V6.0", that version was announced in 2002, i.e. is not really up to date...
Variadic macros in turn were included in the standard only in 1999, so it's quite possible your version of the compiler does not support them yet.
The form:
#define debug(M, s ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ## s)
with s ... is not C but a GNU extension to C. See gcc documentation that states:
If your macro is complicated, you may want a more descriptive name for the variable argument than VA_ARGS. CPP permits this, as an extension. You may write an argument name immediately before the ‘...’; that name is used for the variable argument. The eprintf macro above could be written
#define eprintf(args...) fprintf (stderr, args)
using this extension.
The correct C form for your debug macro would be:
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__,
__LINE__, __VA_ARGS__)
For debugging purposes I would like to have a printf_debug function that would function just like the standard printf function, but would only print if a #DEFINE DEBUG was true
I know I have to use varagrs (...) but I have no idea how to actually achieve that.
Thanks in advance.
Easier to just #define it away. Something like this:
#ifdef DEBUG
#define printf_debug printf
#else
#define printf_debug while(0)printf
#endif
I don't what exactly you want to achieve. In case you want a code block to execute only if DEBUG is defined, use the preprocessor directive #ifdef.
#include <stdio.h>
#include <stdarg.h>
#define DEBUG
void printf_debug(const char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
#endif /* DEBUG */
}
You don't need to use vargs, macros will work. Here is an example, which will prints function and line number as well:
#ifdef DEBUG
#define printf_debug(fmt, args...) printf("%s[%d]: "fmt, __FUNCTION__, __LINE__, ##args)
#else
#define printf_debug(fmt, args...)
#endif
The ##args here will be replaced by the args list, which likes what vargs does in function call.
You have to use the va_arg macros, they are used to access the variadic variables. A useful link: http://www.cppreference.com/wiki/c/other/va_arg. The reference is for C++, but these macros can be used in C as well.
In your actual implementation you place the code using the variadic variables in a #ifdef block.
But if you're looking for a regular call to printf, dependent on DEBUG a simple #define acting as an alias will do.
C99 compiler only!
#include <stdio.h>
#define DEBUG
#ifdef DEBUG
#define debug(...) printf(__VA_ARGS__)
#else
#define debug while(0)
#endif
int main(int argc, char *argv[])
{
debug("Only shows when DEBUG is defined!\n");
return 0;
}
to be honest varidic macros are not needed you could just easily write it as this:
#include <stdio.h>
#define DEBUG
#ifdef DEBUG
#define debug printf
#else
#define debug while(0)
#endif
int main(int argc, char *argv[])
{
debug("Only shows when DEBUG is defined!\n");
return 0;
}
Thinking about it, debug information should go to stderr so as not to interfer with stdout, so this one should be favoured:
#include <stdio.h>
#define DEBUG
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug while(0)
#endif
int main(int argc, char *argv[])
{
debug("Only shows when DEBUG is defined!\n");
return 0;
}
in C, what is the proper way to define a printf like macro that will print only when DEBUG symbol is defined?
#ifdef DEBUG
#define DEBUG_PRINT(???) ???
#else
#define DEBUG_PRINT(???) ???
#endif
where ??? is where I am not sure what to fill in
I've seen this idiom a fair amount:
#ifdef DEBUG
# define DEBUG_PRINT(x) printf x
#else
# define DEBUG_PRINT(x) do {} while (0)
#endif
Use it like:
DEBUG_PRINT(("var1: %d; var2: %d; str: %s\n", var1, var2, str));
The extra parentheses are necessary, because some older C compilers don't support var-args in macros.
#ifdef DEBUG
#define DEBUG_PRINT(...) do{ fprintf( stderr, __VA_ARGS__ ); } while( false )
#else
#define DEBUG_PRINT(...) do{ } while ( false )
#endif
Something like:
#ifdef DEBUG
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, fmt, ## args)
#else
#define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
#endif
Thank you mipadi, I improved your DEBUG_PRINT with file information too.
#define DEBUG 3
#if defined(DEBUG) && DEBUG > 0
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, \
__FILE__, __LINE__, __func__, ##args)
#else
#define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
#endif
Tested with latest clang, e.g.
int main(int argc, char **args) {
DEBUG_PRINT("Debugging is enabled.\n");
DEBUG_PRINT("Debug level: %d", (int) DEBUG);
}
outputs:
DEBUG: debug.c:13:main(): Debugging is enabled.
DEBUG: debug.c:14:main(): Debug level: 3
Use different signatures of DEBUG_PRINT, they don't have to be the same, like:
#ifdef DEBUG
#define DEBUG_PRINT printf
#else
#define DEBUG_PRINT(...)
#endif
this way on debug mode the DEBUG_PRINT call will be replaced with printf. On release it will ignore all arguments used previously.
Hope it helps.
You can simply use:
#ifdef DEBUG
#define DEBUG_PRINT printf
#else
#define DEBUG_PRINT
#endif
I like this way the best because it wont add any asm instructions to your release build.
#define DEBUG
#ifdef DEBUG
#define debug_printf(fmt, ...) printf(fmt, __VA_ARGS__);
#else
#define debug_printf(fmt, ...) /* Do nothing */
#endif
I see some minor errors in this implementation. So, here is my approach:
#ifdef DEBUG
#define DEBUG_PRINTF(...) printf("DEBUG: "__VA_ARGS__)
#else
#define DEBUG_PRINTF(...) do {} while (0)
#endif
Example usage:
DEBUG_PRINTF("hello\n");
Then, if I build and run with the -DDEBUG define on in my C build options, like this:
# Build
gcc -Wall -Wextra -Werror -std=c11 -DDEBUG -o build/my_program \
my_program_tests.c my_program.c
# Run
build/my_program
then I see this output:
DEBUG: hello
But if I build withOUT the -DDEBUG define in my compiler C options, then I see no debug prints whatsoever.