Question

I am getting nuts with this error so I thought some of more experienced developers can help me in this regard. I am trying to compile a sample project which uses a C++ library (named Poco). My project is linked to compiled poco libraries.

Below is my (most simplified) code:

#include "Poco/UUID.h"
class x
{
    void func1()                                        
    {                                                                           
        new Poco::UUID();  //A
    }   
};

void func1()                                        
{                                                                           
    new Poco::UUID();   //B
}

Now when above code is compiled, line 'A' has no error but for line 'B' linker says: undefined reference to `Poco::UUID::UUID()'

What is the reason? When I instantiate a class from external lib in a class method no error occurs but the same code in a function produces linker error? (When I comment line B, no error occurs and linker output files are generated)

My configuration: Win7/g++/CodeLite/MinGW-4.7.1

*Update 2:*Thanks. My problem is now resolved and the issue is that I had compiled library using MSVC compiler while my application was being compiled using g++ (both under Windows platform). So I re-compiled library using g++ and everything works fine now.

Update 1: here is my IDE's output when I build my project:

    C:\Windows\system32\cmd.exe /c "mingw32-make.exe -j 4 -e -f  "dll1.mk"  all"
----------Building project:[ dll1 - Debug ]----------
g++ -shared -fPIC -o ./Debug/dll1.so @"dll1.txt" -L. -Lc:/poco/lib  -lPocoFoundationd
./Debug/PluginLibrary.o: In function `Z5func1v':
C:/Users/PARS/Documents/codelite/workspace1/dll1/PluginLibrary.cpp:12: undefined reference to `Poco::UUID::UUID()'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe: *** [Debug/dll1.so] Error 1
dll1.mk:77: recipe for target `Debug/dll1.so' failed
1 errors, 0 warnings
Was it helpful?

Solution

Your member function x::func1() is never ODR-used in that compilation unit (source file). Most compilers only generate compiled code for a member function defined inside the class definition if that member function is ODR-used within the compilation unit that is being compiled. Suppose some other source file does use x::func1(). If you compile that other source file, the compiler will produce object code for x::func1() in the object file that corresponds to that other source file.

The compiler can get away with bypassing the process of generating compiled code for x::func1() here because the class definition has to be the same across all compilation units. If you compile some other source file that has a different definition of class x you have violated the one definition rule. This is undefined behavior and no diagnosis is required.

If no source file uses x::func1() you have some dead code that just never happens to be compiled. The code has an error but it's never detected.

The compiler cannot get away with bypassing generating compiled code for the free function func1(). This function has external linkage; there's no way the compiler can tell if it might be used somewhere else. The compiler must generate compiled code for that free function.

Here's a minimum working example:

class Missing {
public:
   Missing();
   int value;
};

class UsesMissing {
public:

   int use_missing () {
      Missing missing;
      return missing.value;
   }

   int dont_use_missing () {
      return 0;
   }
};

#ifdef DEFINE_USE_MISSING
int use_missing () {
   Missing missing;
   return missing.value;
}
#endif

int main () {
   UsesMissing test;
#ifdef USE_MISSING
   return test.use_missing();
#else
   return test.dont_use_missing();
#endif
}

Compile with neither DEFINE_USE_MISSING or USE_MISSING defined and this compiles and links just fine with g++ and clang++. Define either one of those flags and the file fails in the link step because of the undefined reference Missing::Missing().

OTHER TIPS

You should link with the correct library to fix your link (see Poco docu for the correct one).

func1 has extern linkage and so linker need Poco::UUID whereas X::func1 is inline/private/unused.

if you use static foo1() or inline foo1() the linker error disappears if you use x::func1 or implement x::func1 outside of the class x{}; the error linker appears

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top