Houston, we have an undefined reference

c++, linker, undefined-reference

Solution

One thing worth checking for is determining whether it's a dead code stripping issue. I've had "undefined reference" linker errors in the past because of this.

The MS compiler will remove code if it's not used. GCC will not do this by default, and if that code uses symbols that aren't defined, you'll get errors. Since the MS compiler removes those calls, you get no errors there. In order to see if this is your problem, add these flags to your compilation flags (both for C++ as well as for C, if you also have C sources):

-fdata-sections -ffunction-sections

And this flag to your link flags:

-Wl,--gc-sections

(Of course make sure you're using `g++` for linking, not `ld`.)

Other than that, my only recommendation is to use a proper build system. I highly recommend CMake. It's easy, reliable, and you should be able to learn it quickly. Creating a CMake-based build for a 300k LOC project with over 100 source files took me less than 3 hours (and at that point it was the first time I ever used CMake.)

Problem

MEGAEDIT 3000 I have discovered the cause of undefined references. I checked my .o files for symbols, and they were just missing. Just weren't there. For no apparent reason. I have checked the source of the compromiting .o file, but everything seemed to be OK. I've thought that it may be one of those nasty `#ifdef ... #endif` blocks, cunningly hidden amongst lines of the code like a bear trap, waiting for its victim. But I couldn't find any. After moving some function definitions to the very end of the file and enclosing them in `#ifdef ... #endif` block suitable for Linux, the symbols magically appeared and everything was fine. Thank you for your time. Outdated, do not read. I have been assigned to one big project lately, my job is to make it run on Linux platforms. Unfortunately, the programmer who wrote the whole project before me did a very poor job, creating whole lots of circular dependencies by including file `B3D_Base.h`, where almost every header is `#included`, to almost every header and source file in the project (that makes 170+ files with `#include "B3D_Base.h"` line). This caused no problems during compilation on both Windows and Linux. However, this causes lots of 'undefined reference' errors during linking phase on Linux, even though all object files and libraries are linked. Being aware of `ld`'s limitation of single iteration through all object files during linking, I'm asking: Is there a way to force `ld` to do multiple iterations through objects and libraries, possibly solving all the 700+ undefined reference errors, or is my only chance to actually link the project just replacing all the `#include "B3D_Base.h"` lines with proper includes to needed headers? APPENDIX #1: Here is an example of what mess I'm supposed to make run on Linux: There is one header file `B3D_Base.h`, to which is included `B3D_Loading3.h`, which contains class `B3D_LOADING3`. File `B3D_Loading3.cpp` is including only `B3D_Base.h` and a memory manager class not included in Base. An instance `B3D_LOADING3 g_Loading3;` is declared in `B3D_Base.h` and initializes+used in many other parts of the project. Everything compiles just fine, but when it comes to linking, I get many `'undefined reference to g_Loading3'` errors. And there are many more errors like this, complaining about undefined references to both class instances and functions alike. So much for clean code. APPENDIX #2: I'll be providing an SSCCE example, as kfsone requested: B3D_Base.h ``` ... (many other includes) #include "B3D_Loading3.h" extern B3D_LOADING3 g_Loading3; ... (includes go on) ``` B3D_Loading3.h/B3D_Loading.cpp ``` a full definition of class B3D_LOADING3, but no real declaration of g_Loading3 ``` AW_Game.cpp (one of the files where g_Loading3 is used) ``` #include "B3D_Base.h" ... (some lines) extern B3D_LOADING3 g_Loading3; ``` Thanks to kfsone who made me go through the code thoroughly, I managed to find out where the problem lies: g_Loading3 is defined everywhere as `extern`, thus not being properly defined. All I needed was to remove the `extern` keyword from one file. Fixed me ~ 30 linking errors. Thanks, kfsone. APPENDIX #3: But there is still problem with undefined references to class functions. After some code scanning, I suppose that the functions are not even defined due to overextended use of `#ifdef ... #endif` clauses (portability) and thus it may be my fault, overlooking functions defined only in some passive ifdef block. I will try to look at this issue and later report if anything changed. APPENDIX #3 REPORT: Even after properly defining functions, the undefined-reference-list did not shrink. The problem is therefore still open for discussion. APPENDIX #3.1 I'll be providing some example code. Foo.h ``` #ifndef FOO_H #define FOO_H class Foo { unsigned int m_size; bool m_lock; friend class ASDF; public: unsigned int m_id; void Release() {delete this;} int Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags); int Unlock(); }; // other class declarations to follow #endif ``` Foo.cpp ``` #include "Foo.h" // other includes and function definitions to follow int Foo::Lock(UINT OffsetToLock, UINT SizeToLock, VOID ** ppbData, DWORD Flags) { if(!m_lock) { // some locking code } return 0; } ``` Baz.cpp ``` #include "Foo.h" // although included, defined and declared, causes undef reference Foo *m_pFoo; // several lines later m_pFoo->Lock(0,0,(void)&Asdf,NULL); // <-- compiles fine, causes undefined reference ```

Original source

Related problems