Sign in to follow this  
koralcem

Variadic macros for debug purposes

Recommended Posts

Hi guys, I was trying to write a variadic macro to be able to check some values as my game is running and I came across the following problem: I want a macro that will check an expression and, if it's false, print the expression that failed along with other info into a text file. I also wanted to allow for printing a custom message, if given. So I have an ASSERT(x, ...) macro which has the following line after all the info printing is done (where err_log is a proper FILE*): fprintf(err_log, "Msg: "__VA_ARGS__); This works as intended when the user does give it a message, but if he doesn't I get "C2660: 'fprintf': function does not take 1 arguments". Shouldn't __VA_ARGS__ amount to nothing if no other parameters are passed? So shouldn't I end up with printing just "Msg: " to the file? I would greatly appreciate it if someone could point out what I'm missing here. Another thing that might help me out: Is there a way, from within the macro, to check whether __VA_ARGS__ will expand to anything at all (i.e. if it's "empty")? If so, maybe I can just put an if/else in there to print nothing if a message wasn't given. A preemptive thanks,

Share this post


Link to post
Share on other sites
The following

#include <cstdio>

#define TEST(x,...) if((x)) { fprintf(stdout,"Msg: " __VA_ARGS__); }

int main() {
TEST(true);
TEST(true,"PRINT\n");
}

produces the expected results for me with VS2008. What's your actual code look like? The error is interesting -- it says you're trying to call fprintf() with one parameter. But you should have at least two, according do your examples. I think the problem lies in part of the code you have not shown us.

Share this post


Link to post
Share on other sites
Excellent point Josh,

Below is the file which will house the macros (hope formatting doesn't blow up):

//-----------------------------------------------------------------------
#ifndef DEBUG_TOOLS_H
#define DEBUG_TOOLS_H
//-----------------------------------------------------------------------

//files needed in the debug macros
#include <stdio.h> //printf(), fprintf()

//-----------------------------------------------------------------------

#ifdef DEBUG_MODE

#define ASSERT(x,...)
{
  if(0 == (x))
  {
    FILE* err_log;
    err_log = fopen("error_log.txt", "wt");
    printf("assert!\n");
    fprintf(err_log, "Failed expression: %s\nIn function: %s\nLine: %d\nIn file: %s\n", #x, __FUNCTION__, __LINE__, __FILE__);
    printf(err_log, "\n");
    fprintf(err_log, "Msg: "__VA_ARGS__);
    fclose(err_log);
  }
}
#else //#ifdef DEBUG_MODE. if DEBUG_MODE isn't defined the macros don't do anything
  #define ASSERT(x)
#endif //#ifdef DEBUG_MODE

//------------------------------------------------------------------------
#endif //DEBUG_TOOLS_H

And my main is simply:

#include "debug_tools.h"

int main(void)
{
  int y = 0;
  ASSERT(y);
  return 0;
}

which produces the following:

error C2143: syntax error : missing ')' before 'string', main.cpp, 6
error C2660: 'fprintf' : function does not take 1 arguments, main.cpp, 6
error C2059: syntax error : ')', main.cpp, Line:6

I am using Visual Studio 2005. Would that make a difference in the way macros are handled?

Share this post


Link to post
Share on other sites
Sorry to have left those out. I do have them in the actual file but apparently I deleted them while trying to make the formatting work in html, and forgot to put them back in.

Edit: Josh, I tried copy/pasting your code exactly into my program and it still complains about calling fprintf with one argument. Could the problem be the compiler?


[Edited by - koralcem on April 22, 2008 11:09:35 PM]

Share this post


Link to post
Share on other sites
What compiler are you using? Its only relatively recently that these have compiled across the different platforms I use at work (VS was a relatively early adopter I think).

Does this compile as expected for you?:

static inline void Foo(...){}
#define ASSERT(x,...) do { Foo(__VA_ARGS__); } while(0)

//Tests (Compile in VS'08)
ASSERT(0, "bob");
ASSERT(0, "bob %s", "and sheila");
ASSERT(0);

Share this post


Link to post
Share on other sites
Quote:

Edit: Josh, I tried copy/pasting your code exactly into my program and it still complains about calling fprintf with one argument. Could the problem be the compiler?

It may be. Your example worked when I copied it. 2005 may have different semantics for the operation of that macro expansion -- could be what's causing it to swallow one of the parameters.

Share this post


Link to post
Share on other sites
Yeah, I'm assuming it's just the compiler then. I'll just make 2 different macros, one for when the user wants to supply a message and one when not. Thanks a lot though, I really appreciate your guys' time.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this