8

I'm working on a debugging/logging program and was wondering if it would be possible to create a macro that I can paste inside each function and it will print the function name and parameter values each time the function's called. Function name can be resovled at compile time, the problem is figuring out how to print parameter values?

UPDATE: I remember reading an article to get parameters but that invovled assembly code and working manipulating stack pointers, which is not cross-platform compatible - something that I need.

tunafish24
  • 2,288
  • 6
  • 28
  • 47

6 Answers6

2

You can use the __FUNCTION__ or __func__ macro for the function name. For the parameters, I don't think there's a built-in macro to achieve this.

Other helpful macros are __LINE__ and __FILE__.

EDIT:

__FUNCTION__ and __func__ are not part of the standard, but they are widely supported.

16.8 deals with predefined macros:

__cplusplus
__DATE__
__FILE__
__LINE__
__STDC_HOSTED__
__TIME__

and macros defined by the implementation:

__STDC__
__STDC_VERSION__
__STDC_ISO_10646__
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 3
    `__func__` *is* part of the standard, but it is not a macro. Perhaps that is why you didn't find it at that place. – Jens Gustedt Mar 01 '12 at 20:24
  • @JensGustedt we talking about the c++ standard? – Luchian Grigore Mar 01 '12 at 20:27
  • no I was talking about C. In C11 it is 6.4.2.2, a predefined identifier, not a macro. AFAIR it was already in C99, so it should be in C++, too. – Jens Gustedt Mar 01 '12 at 20:41
  • @JensGustedt it's not in C++. I don't know if C++11 has it, but before that, no. – Luchian Grigore Mar 01 '12 at 20:47
  • The questioner stated they already knew how to get the function name from a macro -- the stated question was how to use a macro to retrieve na print the function parameters. – Perry Mar 01 '12 at 20:48
  • @Perry I know, and to that I answered `For the parameters, I don't think there's a built-in macro to achieve this.` And there's not, as proven in the last part of the answer, where I list all pre-defined macros from the C++ standard. BTW, how's your answer to my question going? – Luchian Grigore Mar 01 '12 at 20:50
  • Hey @JensGustedt Does your P99 offer an actual macro that would do this? I'm trying to make a UTF8 version of `__func__`, and I'm not entirely sure how to do the actual getting-the-current-functions-name more directly than using `__func__` :/ I'm getting a lot of useless warnings about this and I don't want to disable them, I just wish it'd be a bit smarter. – MarcusJ Feb 16 '18 at 20:42
1

For the function name, you can use the standard (since C99) identifier __func__.

In C++, the GNU extension identifier __PRETTY_FUNCTION__ will also print the parameter types.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • The questioner stated he knew how to get the function name from a macro -- his concern was printing the function parameters. – Perry Mar 01 '12 at 20:47
0

You can use a variadic macro and then pass the string format and the function parameters to it. The macro won't be exactly the same for every function (as every function might have different parameters), but most of the work lies in copy-pasting the parameters that are one line above.

If your function signature is:

void func(char *param1, int param2);

Your macro will be something like:

PROFILE_FUNC(__FILE__, __LINE__, "param1 = %s, param2 = %d", param1, param2);

The part after PROFILE_FUNC(__FILE__, __LINE__,... will be variable. Look in the link on how exactly to do this.

If noone sugested anything better in seven years, it must be the way to go. If you can find how __PRETTY_FUNCTION__ gets the parameter types, you might be able to automate this further.

EDIT

This link is usefull. It describes three ways of how to get the backtrace of your application at runtime:

  1. gcc builtin macro __builtin_return_address
  2. glibc backtrace and backtrace_symbols
  3. libunwind
Niko
  • 642
  • 6
  • 12
0

The C macro system cannot implicitly reference the parameters. You'd have to pass them to it.

As a small win macros can count their arguments, so it would be TRACE(foo,bar) instead of TRACE2, TRACE3 etc. That's not significantly worse than writing TRACE() at the start of the function.

Actually printing the values would be fine. Overload operator<< or hand roll it with _Generic, depending on language.

Doing this sort of thing cleanly, e.g. to infer the parameters, toggle printing on and off dynamically, is accessible via code generators. Two styles of that: 1/ parse the C, or specific comments. See swig, doxygen. 2/ generate the logging functions and the C from something else

Parse the C seems to be more common. Possibly because you can easily add it to existing code. Generating from another input is easier to do reliably. Writing function name, parameter list, string containing the implementation, as XML/JSON works. Beyond templating, I like python and lua scripts that generate C and metadata. See also LLVM's tablegen.

Jon Chesterfield
  • 2,251
  • 1
  • 20
  • 30
0

There is no portable way to get all the parameter values and print them -- you certainly can't do it from a macro. You may have to use another method to achieve what you want.

Perry
  • 4,363
  • 1
  • 17
  • 20
  • what's the other method? I could certainly use a macro to substitute C code. – tunafish24 Mar 01 '12 at 19:59
  • You could do something ugly in which you did all your function declarations using a macro that blatted out code for the function declaration and then printed out their values at the head of the function itself. This is not pretty -- I wouldn't go down that path. That way lies madness. In the real world, just use gdb, or print what you need when you need it. – Perry Mar 01 '12 at 20:06
  • @Perry how would you go about doing that? +1 from me if you can provide a working example. – Luchian Grigore Mar 01 '12 at 20:13
  • It would be really grotesque. The way you would approach it would be to abuse the varadic macro facility and a multi-line macro. I am sure that getting it right (which means dealing properly with the types of the outputs) is going to be a bitch if it can be done with generality at all -- this is worth more than just a +1, this would be a potential contribution to the Obfuscated C Programming contest. (The similar hacks I've seen in the past, for example for a lisp interpreter in C, could depend on all parameters being one type.) – Perry Mar 01 '12 at 21:00
0

Here are some examples and tricks with debugging with macroses. Lists of MS specific and GNU's

Community
  • 1
  • 1
gemelen
  • 619
  • 10
  • 18