2

I have a C program with a multi-line macro and the program crashes within the macro, how can I pinpoint the location within the macro where the crash happens?

Here is a simplified version of my program. In reality CRASHES is multiple lines long and not easily expandable manually.

#include <stdio.h>
#include <stdarg.h>
#define CRASHES(ptr) \
    (*(ptr) == 123)
main()
{
    char *foo = NULL;
    if (CRASHES(foo))
        printf("This will never happen.");
}

When compiling and running this with gdb a.out I get the expected EXC_BAD_ACCESS (I am on Mac OS X with gdb 6.3), however the crash points to line 8 and not line 4 where the crash is actually caused.

I already tried compiling the program with additional debugging flags -gdwarf-2 and -g3 as suggested by the docs and inserted several assert()s within the macro itself. Unfortunately that did not provide more information.

1
  • 2
    why should be line 4? the crash is at line 8, where the macro is expanded and used. The macro causes no segfault intrinsically, it is because of the value of foo, in this case, so it is correct the crash is on line 8. It would be misleading if it would point to 4. Commented Jun 26, 2011 at 20:53

4 Answers 4

8

lots of valuable information here about macro debugging.

...another approach is to use the preprocessor, i.e. compile it using -E and copy-paste the expanded macro into your src-code and see if you can debug from there.

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

2 Comments

That link looks pretty good. In the past I've expanded the macro text with compiler args & then compiled that file & debugged it. Look at the -E option to (g)cc.
Unfortunately info macro ..., etc. produce GDB has no preprocessor macro information for that code even when compiled with the named flags. But compiling with -E and pasting back did it, I just wish GDB would do that for me. :)
1

Of course this crashes since you are deferencing a NULL pointer...(it was not this the question right?). With this particular example, it is easy: gcc -g2, and gdb says

Program received signal SIGSEGV, Segmentation fault.
0x080483d9 in main () at crash.c:10
10      if (CRASHES(foo))

which is rather clear, you expand by yourself the macro and see why (since *foo == 123 access memory you can't read, since foo is NULL). In more complex cases, gcc -E helps, or avoid using macros.

Comments

0

You don't say anything about how it crashes. If it's a segfault, be aware that it might occur a bit later than when you actually dereferenced the bad pointer value.

Comments

-1

I there any way you could convert it to an actual function? This is one of the great evils of macros.

3 Comments

Sometimes it is very hard to convert something to function call (e.g. here google.com/codesearch#XcaBTDeweEI/src/mpid/common/datatype/… - it was done as macro to get performance and not to repeat code for various types)
Unfortunately not easily. The first macro expands another macro multiple times which references local variables. Edit: It's actually very similar to the code osgx referenced.
Fair enough. Although the argument for macros for performance is outdated. Most modern compilers are intelligent enough to automatically inline functions that are small enough to be defined as macros. The need to access local variables is a good argument, which is why I enjoy new languages with anonymous and/or nested functions . . . maybe we'll see that in c/c++ someday. Haha, jk.

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.