C++ assert with time stamp - c++

is that possible to log information when assert failed with time stamp
ex.
int a = 10
assert( a > 100 );
then it will be failed and output just like with the timestamp as well
2013-12-02 , 17:00:05 assert failed !! (a > 100) line : 22
Thank you

assert is a macro (it has to be one, to give __LINE__ and __FILE__ information).
You could define your own. I would name it something else like tassert for readability reasons, perhaps like (untested code)
#ifdef NDEBUG
#define tassert(Cond) do {if (0 && (Cond)) {}; } while(0)
#else
#define tassert_at(Cond,Fil,Lin) do { if ((Cond)) { \
time_t now##Lin = time(NULL); \
char tbuf##Lin [64]; struct tm tm##Lin; \
localtime_r(&now##Lin, &tm##Lin); \
strftime (tbuf##Lin, sizeof(tbuf##Lin), \
"%Y-%m-%d,%T", &tm##Lin); \
fprintf(stderr, "tassert %s failure: %s %s:%d\n", \
#Cond, tbuf##Lin, Fil, Lin); \
abort(); }} while(0)
#define tassert(Cond) tassert_at(Cond,__FILE__,__LINE__)
#endif /*NDEBUG*/
I am using cpp concatenation ## with Lin to lower probability of name collisions, and I am using cpp stringification # to make a string out of Cond macro formal. The Cond is always expanded, to make sure the compiler catch syntactic errors in it even when disabling tassert with NDEBUG as assert(3) does.
One could put most of the code in the above macro in some function, e.g.
void tassert_at_failure (const char* cond, const char* fil, int lin) {
timer_t now = time(NULL);
char tbuf[64]; struct tm tm;
localtime_r (&now, &tm);
strftime (tbuf, sizeof(tbuf), "%Y-%m-%d,%T", &tm);
fprintf (stderr, "tassert %s failure: %s %s:%d\n",
cond, tbuf, fil, lin);
abort();
}
and then just define (a bit like <assert.h> does...)
#define tassert_at(Cond,Fil,Lin) do { if ((Cond)) { \
tassert_at_failure(#Cond, Fil, Lin); }} while(0)
but I don't like much that approach, because for debugging with gdb having  abort() being called in the macro is much easier (IMHO size of code for debugging executables does not matter at all; calling abort in a macro is much more convenient inside gdb - making shorter backtraces and avoiding one down command...). If you don't want libc portability and just use recent GNU libc you could simply redefine the Glibc specific __assert_fail function (see inside <assert.h> header file). YMMV.
BTW, in real C++ code I prefer to use << for assertion-like debug outputs. This enables usage of my own operator << outputting routines (if you give it as an additional macro argument) so I am thinking of (untested code!)
#define tassert_message_at(Cond,Out,Fil,Lin) \
do { if ((Cond)) { \
time_t now##Lin = time(NULL); \
char tbuf##Lin [64]; struct tm tm##Lin; \
localtime_r(&now##Lin, &tm##Lin); \
strftime (tbuf##Lin, sizeof(tbuf##Lin), \
"%Y-%m-%d,%T", &tm##Lin); \
std::clog << "assert " << #Cond << " failed " \
tbuf##Lin << " " << Fil << ":" << Lin \
<< Out << std::endl; \
abort (); } } while(0)
#define tassert_message(Cond,Out) \
tassert_message_at(Cond,Out,__FILE__,__LINE__)
and then I would use tassert_message(i>5,"i=" << i);
BTW, you might want to use syslog(3) instead of fprintf in your tassert_at macro.

Related

What are the performance impacts that Expects(cond) of the GSL imposes on the runtime?

The CPP Core Guidelines propose to use Expects(expression) to state preconditions and Ensures(expression) to state postconditions from the GSL in functions.
Example:
int area(int height, int width)
{
Expects(height > 0 && width > 0); // good
if (height <= 0 || width <= 0) my_error(); // obscure
// ...
}
What is the performance impact of these macros?
Is it just as checking the condition with if and then throwing an exception?
Is there a difference between debug and non-debug mode?
I.e. are the macros also active if the app is built as a release?
I ask because I am thinking about using it as a good practice, i.e. try, if there is not a specific reason against it, just stating possible pre/post conditions (assuming it is not sensible to use different types as parameters) using these macros from the GSL.
These macros are defined in the gsl_assert header.
Here's the relevant code:
#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) \
: gsl::details::throw_exception(gsl::fail_fast( \
"GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__))))
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
As you can see, it depends on how you choose to handle contract violations. In the first two cases, you will pay the cost of a branch plus either throwing an exception or calling std::terminate.
In the case that GSL_UNENFORCED_ON_CONTRACT_VIOLATION is defined, the macros will expand to GSL_ASSUME:
//
// GSL_ASSUME(cond)
//
// Tell the optimizer that the predicate cond must hold. It is unspecified
// whether or not cond is actually evaluated.
//
#ifdef _MSC_VER
#define GSL_ASSUME(cond) __assume(cond)
#elif defined(__GNUC__)
#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable())
#else
#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0)
#endif
In that case, the condition might or might not be evaluated depending on the compiler. It can also make your code faster as the compiler might be able to optimize more aggressively thanks to the assumptions.
There is no deactivation as for an assert, the condition will be tested all the time:
#if defined(__clang__) || defined(__GNUC__)
#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define GSL_LIKELY(x) (!!(x))
#define GSL_UNLIKELY(x) (!!(x))
#endif
And then yes, it throws an exception or even terminate depending on your settings:
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) \
: gsl::details::throw_exception(gsl::fail_fast( \
"GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__))))
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) \
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
If GSL_UNENFORCED_ON_CONTRACT_VIOLATION is set, nothing happens.
I have a feeling that Expects is slightly against the spirit of C++ (as I perceive this spirit) ... Maybe it would really be good if C++ was more mainstream and Java-like but for me its original idea is to provide maximum performance (sometimes at the cost of less safety/more complexity/lower readability). I think we can obtain both goals without sacrifising performance. For me the solution is quite simple - custom assert (cassert) - that is the fast assert that can be switched on or off for release builds.
Sample implementation (Windows only) :
// cassert.h:
#pragma once
// Switch this macro off for maximum performance release builds:
#define __RELEASE_WITH_ASSERTS__
#ifndef cassert
#if defined(_DEBUG) || defined(__RELEASE_WITH_ASSERTS__)
void __cassert(bool val, const char* szFile, int line, const char* szDesc);
#define cassert(a) ((a) ? ((void)1) : __cassert(a, __FILE__, __LINE__, _CRT_STRINGIZE(#a)))
#else
#define cassert(a)
#endif
#endif
// cassert.cpp
#if defined(_DEBUG) || defined(__RELEASE_WITH_ASSERTS__)
void __cassert(bool val, const char* szFile, int line, const char* szDesc)
{
if (!val)
{
std::string sIgnore;
int mode;
#if defined(_DEBUG)
sIgnore = "\n\nIgnore assertion?";
mode = MB_YESNO;
#else
sIgnore = "";
mode = MB_OK;
#endif
char szLine[16];
_itoa(line, szLine, 10);
std::string sAssertion = std::string("Assertion failed in file ") + szFile + " at line " + szLine + "\n" + szDesc;
Log(sAssertion.c_str());
if (MessageBoxA(NULL, (std::string("Assertion failed in file ") + szFile + " at line " + szLine + "\n" + szDesc + sIgnore).c_str(), "Assertion failed", mode | MB_ICONINFORMATION) == IDNO)
_CrtDbgBreak();
}
}
#endif
Such cassert will make even debug builds run much faster because there is no actual call to (c)assert function, if condition is satisfied (and every such call would be quite heavy because of _CRT_STRINGIZE(#a) (condition as a string).

Using boost.log with printf-style macros

I'm working on an application that uses an custom, platform-dependent logger. The application defines some printf-style macros:
#define LOG_DEBUG(format, ...) \
logger.log(DEBUG, __FUNCTION__, format, ##__VA_ARGS__)
...
The past few days I've been working on moving the application to use boost.log. The biggest problem I'm having is trying to retain this macro format so that only the logger internals need to be changed, since boost's logging API is implemented in iostream-style, i.e.
BOOST_LOG(logger) << "something";
Is there an easy way to provide a macro that takes printf-style args and prints them to the boost logger without having to use string buffers? (I would think that having to format to a string would be a performance impact)
If not, is there a way to format a string using va_args without having to #ifdef for different platform implementations of formatting functions? (this was the whole point of moving to boost.log in the first place)
Or just use Boost Format to deal with the printf format string. For example,
template<typename Level, typename T1>
inline void log_format(
const Level level,
const char* const fmt,
const T1& t1)
{
BOOST_LOG_SEV(logger::get(), level) << boost::format(fmt) % t1;
}
Creating logger and extending this to handle multiple arguments (most probably with variadic template arguments) is left as an exercise for the reader.
Unfortunately, there are no clean implementations without the #ifdef statement. I know you want to port your existing logging to boost log as-is. That would be an incorrect way of doing things. printf was designed to be used for C, while boost log was designed for C++. So, my suggestion would be to use it the right way. You can make your logging macros painless than what you've shown in your code sample.
Here's my implementation of boost log where instead of having BOOST_LOG(logger) << "something";, I have it as roLOG_INFO << "something";. I believe this example comes from one of boost log's samples.
RoLog.h
#include <boost/logging/format_fwd.hpp>
#include <boost/logging/writer/on_dedicated_thread.hpp>
// Optimize : use a cache string, to make formatting the message faster
BOOST_LOG_FORMAT_MSG( optimize::cache_string_one_str<> )
#ifndef BOOST_LOG_COMPILE_FAST
#include <boost/logging/format.hpp>
#include <boost/logging/writer/ts_write.hpp>
#endif
// Specify your logging class(es)
typedef boost::logging::logger_format_write< > log_type;
// Declare which filters and loggers you'll use
BOOST_DECLARE_LOG_FILTER(roLogFilter, boost::logging::level::holder)
BOOST_DECLARE_LOG(roLog, log_type)
#define roLOG_WHERE_EACH_LINE 0
#if defined(roLOG_WHERE_EACH_LINE) && roLOG_WHERE_EACH_LINE
# define _roLOG_WHERE << roWHERE
#else
# define _roLOG_WHERE
#endif
// Define the macros through which you'll log
#define roLOG_DBG BOOST_LOG_USE_LOG_IF_LEVEL(roLog(), roLogFilter(), debug ) << "[ DEBUG ]:" _roLOG_WHERE
#define roLOG_WARN BOOST_LOG_USE_LOG_IF_LEVEL(roLog(), roLogFilter(), warning) << "[ WARNING ]:" _roLOG_WHERE
#define roLOG_ERR BOOST_LOG_USE_LOG_IF_LEVEL(roLog(), roLogFilter(), error ) << "[ ERROR ]:" _roLOG_WHERE
#define roLOG_CRIT BOOST_LOG_USE_LOG_IF_LEVEL(roLog(), roLogFilter(), fatal ) << "[ CRITICAL]:" _roLOG_WHERE
#define roLOG_INFO BOOST_LOG_USE_LOG_IF_LEVEL(roLog(), roLogFilter(), info )
struct RoLogOptions;
void roInitLogs(const RoLogOptions& options);
RoLog.cpp
#include <Core/RoLog.h>
#include <Core/RoLogOptions.h>
#include <boost/logging/format.hpp>
#include <boost/logging/writer/ts_write.hpp>
using namespace boost::logging;
BOOST_DEFINE_LOG(roLog, log_type)
BOOST_DEFINE_LOG_FILTER(roLogFilter, level::holder)
#define BLOCK(stmts) do{stmts}while(false)
#define CHECK_AND_DO(var,stmt) if (var) stmt
//------------------------------------------------------------------------------
void roInitLogs(const RoLogOptions& options)
{
static bool initialize = true;
if (initialize)
{
// Add formatters and destinations
// That is, how the message is to be formatted...
CHECK_AND_DO(options.printIndex, roLog()->writer().add_formatter(formatter::idx()));
CHECK_AND_DO(options.printTimestamp, roLog()->writer().add_formatter(formatter::time(options.timestampFormat)));
CHECK_AND_DO(options.autoAppendLine, roLog()->writer().add_formatter(formatter::append_newline()));
// ... and where should it be written to
roLog()->writer().add_destination(destination::dbg_window());
CHECK_AND_DO(options.printToStdOut, roLog()->writer().add_destination(destination::cout()));
if (!options.logFile.empty())
{
destination::file_settings settings;
settings.do_append(options.logFileAppendExisting);
roLog()->writer().add_destination(destination::file(options.logFile, settings));
}
CHECK_AND_DO(options.turnOffCache, roLog()->turn_cache_off());
// ... and set the log-level
level::type boost_log_level;
switch(options.logLevel)
{
case eLogLevel_None:
boost_log_level = level::disable_all;
break;
case eLogLevel_All:
boost_log_level = level::enable_all;
break;
case eLogLevel_Debug:
boost_log_level = level::debug;
break;
case eLogLevel_Info:
boost_log_level = level::info;
break;
case eLogLevel_Warning:
boost_log_level = level::warning;
case eLogLevel_Error:
boost_log_level = level::error;
break;
case eLogLevel_Critical:
boost_log_level = level::fatal;
break;
case eLogLevel_Default:
default:
# ifdef _DEBUG
boost_log_level = level::debug;
# else
boost_log_level = level::info;
# endif // _DEBUG
break;
};
roLogFilter()->set_enabled(boost_log_level);
initialize = false;
}
}
DISCLAIMER: I'm not claiming this to be a perfect piece of code. It works for me and I'm happy with it.
Let's say you would still like the option of logging the printf style, then consider the following code:
class LogUtil
{
static void VLogError(const char* format, va_list argList)
{
#ifdef _WIN32
int32 size = _vscprintf(format, argList) + 1;
#else
int32 size = vsnprintf(0, 0, format, argList) + 1;
#endif
if (size > 0)
{
boost::scoped_array<char> formattedString(new char[size]);
vsnprintf(formattedString.get(), size, format, argList);
roLOG_ERR << formattedString.get();
}
}
}
#define roLOGF_ERR(format, ...) LogUtil::VLogError(format, ##__VA_ARGS)
DISCLAIMER: I haven't tested the above code. You might need to tweak it to make it work for you.

Mixing C/C++ using macros and C style strings

gcc/g++ 4.7.2
CXXFLAGS -Wall -Wextra -g -O2
Hello,
I have this header file (mu_test.h) that is written using C style. It contain the following marcos
#define GET_ERROR() ((errno == 0) ? "None" : strerror(errno))
#define LOG_ERR(fmt, ...) fprintf(stderr, "[ERROR] %s:%d: errno: %s " fmt "\n", __func__, __LINE__, GET_ERROR(), ##__VA_ARGS__)
#define MU_ASSERT(test, msg) do { \
if(!(test)) { \
LOG_ERR(msg); \
return msg; \
} \
} while(0)
I have a cpp file (floor_plan_src.cpp) compiled using g++ that includes the mu_test.h
#include "mu_test.h"
char* test_memory_allocation()
{
plan = new floor_plan();
MU_ASSERT(plan != NULL, "Failed to allocate memory for floor_plan");
return NULL;
}
I get this warning:
deprecated conversion from string constant to ‘char*’
So my string constant that I am passing to that function-like marco doesn't like it (C strings) as I have compiled my source using g++.
I thought this problem was to do with mixing c/c++.
solution 1: wrap all the macros in the mu_test.h with extern "C"
#ifdef __cplusplus
extern "C"
{
#endif /* _cplusplus */
#define GET_ERROR() ((errno == 0) ? "None" : strerror(errno))
#define LOG_ERR(fmt, ...) fprintf(stderr, "[ERROR] %s:%d: errno: %s " fmt "\n", __func__, __LINE__, GET_ERROR(), ##__VA_ARGS__)
#define MU_ASSERT(test, msg) do { \
if(!(test)) { \
LOG_ERR(msg); \
return msg; \
} \
} while(0)
#ifdef __cplusplus
}
#endif /* __cplusplus */
Solution 1 still gave me the same warning.
solution 2: wrap the header file in floor_plan_src.cpp
extern "C" {
#include "mu_test.h"
}
Solution 2 still gave me the same warning
Solution 3: wrap the function
extern "C" char* test_memory_allocation()
{
plan = new floor_plan();
MU_ASSERT(plan != NULL, "Failed to allocate memory for floor_plan");
return NULL;
}
Solution 3 same as above
Solution 4:
Try and convert the constant string to a non-const char*
MU_ASSERT(plan != NULL, (char*)"Failed to allocate memory for floor_plan");
gave the following error:
expected primary-expression before char
"[ERROR] %s:%d: errno: %s " cannot be used as a function
Many thanks for any suggestions,
The problem is that your test_memory_allocation might return a string literal, and you shouldn't make a string literal decay to non-const char*: it's allowed in C++, but still deprecated.
Your code gets expanded in:
char* test_memory_allocation()
{
plan = new floor_plan();
do {
if(!(plan != NULL)) {
LOG_ERR("Failed to allocate memory for floor_plan")
return "Failed to allocate memory for floor_plan";
}
} while(0);
return NULL;
}
To fix it you just need to make test_memory_allocation return a const char* or otherwise you could return a pointer to something that could decay to a non-const char* (for example a static char array or to a heap-allocated memory area).
extern "C" is only needed to avoid C++ name mangling, it only affects functions, not macros.

How to create a macro that throws on verifying HR and also logs?

I have a scenario in the code where the following pattern exist -
if (!function(A))
{
log("this is the %d error in this file called %s", num, fileName);
throw AppException(FUNCTION_ERROR);
}
the issue with this is you need to do this all the time and the code looks really dirty. so I want to define a macro like -
#define VerifyOrThrow(b, retcode, logerror)
if (b == 0) \
{ \
log(logerror,arg1, arg2) -->this is the issue \
throw(AppException(retcode)); \
}
then I can use it like this in a single line
VerifyOrThrow(functionA(), FUNCTION_ERROR,this is the %d error in this file called %s);
The issue is I am not sure how to define the macro for the variable length argument for the log string.
Any ideas?
Use __VA_ARGS__ as:
#define VerifyOrThrow(b, retcode, ...)
if (b == 0) \
{ \
log(__VA_ARGS__); \
throw(AppException(retcode)); \
}
My favourite logging macro in C++:
#define ATHROW( msg ) \
{ \
std::ostringstream os; \
os << msg; \
throw ALib::Exception( os.str(), __LINE__, __FILE__ ); \
}
In this case, I throw an exception, but you could do whatever you want after you have formatted the string. In use:
ATHROW( "The value of x is " << x << " when it should be " << correct );
This has all the advantages of the C++ stream output system - type safety, extensibility etc. It is also portable, which the use of variadic macros is currently not (they are not part of the current C++ standard).

How do you create a debug only function that takes a variable argument list? Like printf()

I'd like to make a debug logging function with the same parameters as printf. But one that can be removed by the pre-processor during optimized builds.
For example:
Debug_Print("Warning: value %d > 3!\n", value);
I've looked at variadic macros but those aren't available on all platforms. gcc supports them, msvc does not.
I still do it the old way, by defining a macro (XTRACE, below) which correlates to either a no-op or a function call with a variable argument list. Internally, call vsnprintf so you can keep the printf syntax:
#include <stdio.h>
void XTrace0(LPCTSTR lpszText)
{
::OutputDebugString(lpszText);
}
void XTrace(LPCTSTR lpszFormat, ...)
{
va_list args;
va_start(args, lpszFormat);
int nBuf;
TCHAR szBuffer[512]; // get rid of this hard-coded buffer
nBuf = _vsnprintf(szBuffer, 511, lpszFormat, args);
::OutputDebugString(szBuffer);
va_end(args);
}
Then a typical #ifdef switch:
#ifdef _DEBUG
#define XTRACE XTrace
#else
#define XTRACE
#endif
Well that can be cleaned up quite a bit but it's the basic idea.
This is how I do debug print outs in C++. Define 'dout' (debug out) like this:
#ifdef DEBUG
#define dout cout
#else
#define dout 0 && cout
#endif
In the code I use 'dout' just like 'cout'.
dout << "in foobar with x= " << x << " and y= " << y << '\n';
If the preprocessor replaces 'dout' with '0 && cout' note that << has higher precedence than && and short-circuit evaluation of && makes the whole line evaluate to 0. Since the 0 is not used the compiler generates no code at all for that line.
Here's something that I do in C/C++. First off, you write a function that uses the varargs stuff (see the link in Stu's posting). Then do something like this:
int debug_printf( const char *fmt, ... );
#if defined( DEBUG )
#define DEBUG_PRINTF(x) debug_printf x
#else
#define DEBUG_PRINTF(x)
#endif
DEBUG_PRINTF(( "Format string that takes %s %s\n", "any number", "of args" ));
All you have to remember is to use double-parens when calling the debug function, and the whole line will get removed in non-DEBUG code.
Ah, vsprintf() was the thing I was missing. I can use this to pass the variable argument list directly to printf():
#include <stdarg.h>
#include <stdio.h>
void DBG_PrintImpl(char * format, ...)
{
char buffer[256];
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);
printf("%s", buffer);
va_end(args);
}
Then wrap the whole thing in a macro.
Another fun way to stub out variadic functions is:
#define function sizeof
#CodingTheWheel:
There is one slight problem with your approach. Consider a call such as
XTRACE("x=%d", x);
This works fine in the debug build, but in the release build it will expand to:
("x=%d", x);
Which is perfectly legitimate C and will compile and usually run without side-effects but generates unnecessary code. The approach I usually use to eliminate that problem is:
Make the XTrace function return an int (just return 0, the return value doesn't matter)
Change the #define in the #else clause to:
0 && XTrace
Now the release version will expand to:
0 && XTrace("x=%d", x);
and any decent optimizer will throw away the whole thing since short-circuit evaluation would have prevented anything after the && from ever being executed.
Of course, just as I wrote that last sentence, I realized that perhaps the original form might be optimized away too and in the case of side effects, such as function calls passed as parameters to XTrace, it might be a better solution since it will make sure that debug and release versions will behave the same.
In C++ you can use the streaming operator to simplify things:
#if defined _DEBUG
class Trace
{
public:
static Trace &GetTrace () { static Trace trace; return trace; }
Trace &operator << (int value) { /* output int */ return *this; }
Trace &operator << (short value) { /* output short */ return *this; }
Trace &operator << (Trace &(*function)(Trace &trace)) { return function (*this); }
static Trace &Endl (Trace &trace) { /* write newline and flush output */ return trace; }
// and so on
};
#define TRACE(message) Trace::GetTrace () << message << Trace::Endl
#else
#define TRACE(message)
#endif
and use it like:
void Function (int param1, short param2)
{
TRACE ("param1 = " << param1 << ", param2 = " << param2);
}
You can then implement customised trace output for classes in much the same way you would do it for outputting to std::cout.
What platforms are they not available on? stdarg is part of the standard library:
http://www.opengroup.org/onlinepubs/009695399/basedefs/stdarg.h.html
Any platform not providing it is not a standard C implementation (or very, very old). For those, you will have to use varargs:
http://opengroup.org/onlinepubs/007908775/xsh/varargs.h.html
Part of the problem with this kind of functionality is that often it requires
variadic macros. These were standardized fairly recently(C99), and lots of
old C compilers do not support the standard, or have their own special work
around.
Below is a debug header I wrote that has several cool features:
Supports C99 and C89 syntax for debug macros
Enable/Disable output based on function argument
Output to file descriptor(file io)
Note: For some reason I had some slight code formatting problems.
#ifndef _DEBUG_H_
#define _DEBUG_H_
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "stdarg.h"
#include "stdio.h"
#define ENABLE 1
#define DISABLE 0
extern FILE* debug_fd;
int debug_file_init(char *file);
int debug_file_close(void);
#if HAVE_C99
#define PRINT(x, format, ...) \
if ( x ) { \
if ( debug_fd != NULL ) { \
fprintf(debug_fd, format, ##__VA_ARGS__); \
} \
else { \
fprintf(stdout, format, ##__VA_ARGS__); \
} \
}
#else
void PRINT(int enable, char *fmt, ...);
#endif
#if _DEBUG
#if HAVE_C99
#define DEBUG(x, format, ...) \
if ( x ) { \
if ( debug_fd != NULL ) { \
fprintf(debug_fd, "%s : %d " format, __FILE__, __LINE__, ##__VA_ARGS__); \
} \
else { \
fprintf(stderr, "%s : %d " format, __FILE__, __LINE__, ##__VA_ARGS__); \
} \
}
#define DEBUGPRINT(x, format, ...) \
if ( x ) { \
if ( debug_fd != NULL ) { \
fprintf(debug_fd, format, ##__VA_ARGS__); \
} \
else { \
fprintf(stderr, format, ##__VA_ARGS__); \
} \
}
#else /* HAVE_C99 */
void DEBUG(int enable, char *fmt, ...);
void DEBUGPRINT(int enable, char *fmt, ...);
#endif /* HAVE_C99 */
#else /* _DEBUG */
#define DEBUG(x, format, ...)
#define DEBUGPRINT(x, format, ...)
#endif /* _DEBUG */
#endif /* _DEBUG_H_ */
Have a look at this thread:
How to make a variadic macro (variable number of arguments)
It should answer your question.
This is what I use:
inline void DPRINTF(int level, char *format, ...)
{
# ifdef _DEBUG_LOG
va_list args;
va_start(args, format);
if(debugPrint & level) {
vfprintf(stdout, format, args);
}
va_end(args);
# endif /* _DEBUG_LOG */
}
which costs absolutely nothing at run-time when the _DEBUG_LOG flag is turned off.
This is a TCHAR version of user's answer, so it will work as ASCII (normal), or Unicode mode (more or less).
#define DEBUG_OUT( fmt, ...) DEBUG_OUT_TCHAR( \
TEXT(##fmt), ##__VA_ARGS__ )
#define DEBUG_OUT_TCHAR( fmt, ...) \
Trace( TEXT("[DEBUG]") #fmt, \
##__VA_ARGS__ )
void Trace(LPCTSTR format, ...)
{
LPTSTR OutputBuf;
OutputBuf = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, \
(size_t)(4096 * sizeof(TCHAR)));
va_list args;
va_start(args, format);
int nBuf;
_vstprintf_s(OutputBuf, 4095, format, args);
::OutputDebugString(OutputBuf);
va_end(args);
LocalFree(OutputBuf); // tyvm #sam shaw
}
I say, "more or less", because it won't automatically convert ASCII string arguments to WCHAR, but it should get you out of most Unicode scrapes without having to worry about wrapping the format string in TEXT() or preceding it with L.
Largely derived from MSDN: Retrieving the Last-Error Code
Not exactly what's asked in the question . But this code will be helpful for debugging purposes , it will print each variable's value along with it's name . This is completely type independent and supports variable number of arguments.
And can even display values of STL's nicely , given that you overload output operator for them
#define show(args...) describe(#args,args);
template<typename T>
void describe(string var_name,T value)
{
clog<<var_name<<" = "<<value<<" ";
}
template<typename T,typename... Args>
void describe(string var_names,T value,Args... args)
{
string::size_type pos = var_names.find(',');
string name = var_names.substr(0,pos);
var_names = var_names.substr(pos+1);
clog<<name<<" = "<<value<<" | ";
describe(var_names,args...);
}
Sample Use :
int main()
{
string a;
int b;
double c;
a="string here";
b = 7;
c= 3.14;
show(a,b,c);
}
Output :
a = string here | b = 7 | c = 3.14
Having come across the problem today, my solution is the following macro:
static TCHAR __DEBUG_BUF[1024];
#define DLog(fmt, ...) swprintf(__DEBUG_BUF, fmt, ##__VA_ARGS__); OutputDebugString(__DEBUG_BUF);
You can then call the function like this:
int value = 42;
DLog(L"The answer is: %d\n", value);