Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC Optimization results in "Undefined symbol" at runtime

I right now have a problem that is rather confusing to me: I have piece of software written in C++ and that links against a library in C. I include the header classes using the usual

extern "C" {
    #include <libheader.h>
}

Everything works fine as long as I do not use gcc's optimization. Once I turn on even -O1, thus the first optimization level, during runtime I get an "undefined symbol" error for an symbol from this library. However, the name has gone through name mangling which should be disabled cause of the extern "C".

The function that calls the symbol in question is inlined, in case this matters. The used compiler is gcc 4.4.3.

I honestly don't even have an idea what to search for, so I would be really grateful if one of you could give me some reason for this behaviour.

Thank you for your support.

like image 709
Thilo Avatar asked Mar 30 '11 12:03

Thilo


3 Answers

You say that you're including the libheader.h file in an extern "C" block, but that the symbol the linker is looking for has been name-mangled.

That's an indication that libheader.h is also being included outside of the extern "C" block (the include inside the extern "C" block is probably a nop due to include guards in libheader.h).

Look for other ways that libheader.h might be getting included. GCC's -E and/or the various -M options may or may not help with this. Or (if only for a test) move the extern "C" block inside libheader.h:

// at start of libheader.h:
#ifdef __cplusplus
extern "C" {
#endif

/* existing contents of libheader.h */
// ...

// at end of libheader.h:
#ifdef __cplusplus
}
#endif

Note that linkage specifications can nest, so you don't have to remove the existing extern "C" blocks at the #include sites.

I don't know why the problem would happen only for optimized builds, except that maybe the .c or .cpp file that contains the non-inline version of the calling function gets the headers right, and there only needs to be one translation unit that gets the headers wrong and inlines the calling function to see the problem.

like image 177
Michael Burr Avatar answered Nov 17 '22 00:11

Michael Burr


If you have a function that is defined when not inlined but not defined when inlined, then the problem should be pretty simple to define.

You have used the function somewhere without including its header file.

Review all the files that call this function and make sure the header is included.

like image 36
Zan Lynx Avatar answered Nov 17 '22 00:11

Zan Lynx


Is it possible that the header that defines the calling inline function includes the library's header without the extern "C" wrapper, and everywhere else the wrapper lines are used?

Did you try other levels like -O2?

Did you try uninlining your function?

like image 40
Mark B Avatar answered Nov 17 '22 01:11

Mark B