2

I'm expanding our internal debugging library, and I've run into an odd wall. I'd like to output a variable name as a string. From elsewhere on this site, I found that a macro can be used to do this within a file:

#define VarToStr(v) #v
...
printf("%s\n", VarToStr(MatName));

This outputs MatName. But now let's try this through a function across files (Matrix is a defined type):

// DebugHelpers.h
#define VarToStr(v) #v
...
void PrintMatrix(const Matrix &InputMat)
{
    printf("%s\n", VarToStr(InputMat));
    ... // output InputMat contents
}

// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PrintMatrix(MatName);
}

This outputs InputMat, instead of MatName. How can a function in another file get the variable name from the calling file?

While more complex solutions (wrapper classes, etc.) would be useful for the larger community, my implementation needs to minimize impact to preexisting code/classes.


Update:

Inspired by zenith's comments, I implemented both of his proposed solutions for comparison's sake and got both working quickly. The macro works well for simple outputs, while the function allows for more complex work (and type checking/overloading). I hadn't known that preprocessor macros could be so complex. I'll remember both for future use. Thanks !

5
  • 6
    Not possible. InputMat is called InputMat, no matter where its value came from. Commented Aug 12, 2015 at 15:18
  • 3
    C/C++ is undefined due to there being no sequencing point (unless you've overloaded ++), Commented Aug 12, 2015 at 15:20
  • @Bathsheba ha ! good one :p Commented Aug 12, 2015 at 15:20
  • @Bathsheba: (Good one!) Overloading would be C++ only, so the C tag can be removed? Commented Aug 12, 2015 at 15:21
  • 2
    The "#" stringizes the text to which you prefix it; it's a pre-processor feature and doesn't know about scope or data types, so you can't use it for what you described. Commented Aug 12, 2015 at 15:21

3 Answers 3

10

You can't. Neither C nor C++ retain variable names at runtime.

All your macros are doing is substituting text which happens at compile time.

Sign up to request clarification or add additional context in comments.

Comments

4

As mentioned by others, C++ doesn't support runtime reflection, so if you want to have a string whose contents will only be known at runtime (which is when the call to PrintMatrix will happen), you need to pass it as an argument.

And because you always know what your variables' names are you don't need the VarToStr macro:

// DebugHelpers.h
void PrintMatrix(const Matrix &InputMat, const char* MatName)
{
    printf("%s\n", MatName);
    ... // output InputMat contents
}

// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PrintMatrix(MatName, "MatName");
}

But there's another choice: make PrintMatrix a macro itself, since it's only a debug thing anyway:

// DebugHelpers.h
#define PRINT_MATRIX(InputMat)\
printf(#InputMat "\n");\
... // output InputMat contents


// DataAnalysis.cc
#include DebugHelpers.h
...
void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    PRINT_MATRIX(MatName);
}

Now after preprocessing, AnalysisSubProgram342 will look like this:

void AnalysisSubProgram342()
{
    Matrix MatName;
    ...
    printf("MatName\n");
    ... // output InputMat contents
}

2 Comments

Plus one, if anything, for using const char*
And because you always know what your variables' names are you don't need the VarToStr macro ... the string may or may not be updated when refactoring with a tool.
1

In general you cannot do that (getting the name of a variable at runtime, from e.g. its address or in C++ its reference).

I am focusing on Linux:

However, on Linux (and GNU glibc based systems), for global variables (and functions), you might use the GNU specific dladdr(3) function.

If all the relevant code was compiled with -g (to get debug info), you might parse the debug information in DWARF format (perhaps also using __builtin_frame_address, etc.). With some pain, you might be able to get the name of some local variables from its address on the call stack. This would be a significant effort (probably months of work). Ian Taylor's libbacktrace (inside GCC) might be useful as a starting point.

You could also start (assuming everything is compiled with -g), with e.g. popen(3), a gdb -p debugging process.

Notice that recent GDB debugger is scriptable in Python or Guile, so practically speaking developing Python or Guile functions for GDB would be quicker.

You could also simply add debug output like here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.