views:

6866

answers:

4

Hi,

I'm setting up a C++ project, on Ubuntu x64, using Eclipse-CDT. I'm basically doing a hello world and linking to a commerical 3rd party library.

I've included the header files, linked to their libraries, but I still get linker errors. Are there some possible problems here other than the obvious (e.g. I am 99% sure I'm linking to the correct library).

  1. Is there a way to confirm the static libraries I am linking to are 64bit?
  2. Is there a way to confirm that the library has the class (and methods) I am expecting it to have?

Eclipse says:

Building target: LinkProblem
Invoking: GCC C++ Linker
g++ -L/home/notroot/workspace/somelib-3/somelib/target/bin -o"LinkProblem"  ./src/LinkProblem.o   -lsomelib1 -lpthread -lsomelib2 -lsomelib3
./src/LinkProblem.o: In function `main':
/home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17: undefined reference to `SomeClass::close()'
./src/LinkProblem.o: In function `SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `SomeClass::SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151: undefined reference to `SomeClass::~SomeClass()'
./src/LinkProblem.o: In function `~SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
collect2: ld returned 1 exit status
make: *** [LinkProblem] Error 1
+11  A: 

Assuming those methods are in one of the libs it looks like an ordering problem.

When linking libraries into an executable they are done in the order they are declared.
Also the linker will only take the methods/functions required to resolve currently oustanding dependencies. If a subsequent library then uses methods/functions that were not originally required by the objects you will have missing dependencies.

How it works:

  • Take all the object files and combine them into an executable
  • Resolve any dependecies among object files.
  • Foreach library in order:
    • Check unresolved dependencies and see if the lib resolves them.
    • If so load required part into the executable.

Example:

Objects requires:

  • Open
  • Close
  • BatchRead
  • BatchWrite

Lib 1 provides:

  • Open
  • Close
  • read
  • write

Lib 2 provides

  • BatchRead (but uses lib1:read)
  • BatchWrite (but uses lib1:write)

If linked like this:

gcc -o plop plop.o -l1 -l2

Then the linker will fail to resolve the read and write symbols.

But if I linki the application like this:

gcc -o plop plop.o -l2 -l1

Then it will link correctly. As l2 resolves the BatchRead and BatchWrite dependencies but also adds two new ones (read and write). When we link with l1 next all four dependencies are resolved.

Martin York
Are you referring to the order of the lib files on the G++ command line?
Alex Black
Yes. :-)
Martin York
Thanks, I've tried playing with the order, no luck yet.
Alex Black
I notice your example uses "gcc" whereas my question uses "g++", should I use "gcc" instead?
Alex Black
No use what you were using.If your code contains C++ stuff you will need to use g++ to get the correct standard libraries.
Martin York
Thanks, that was it, I had the order wrong, it works now.
Alex Black
this really helped me! My groupproject suddenly stopped accepting new cpp files from one of my libs, it was all about undefined reference, then I switched positions and it worked as a charm. Seriously, there should be a more specific article on some pages out there about this issue. Thanks a lot Martin!
Jonathan
A: 

Write method definitions in the same order you have mentioned in the header file.

Sandip
+1  A: 

This linker error usually (in my experience) means that you've overridden a virtual function in a child class with a declaration, but haven't given a definition for the method. For example:

class Base
{
    virtual void f() = 0;
}
class Derived : public Base
{
    void f();
}

But you haven't given the definition of f. When you use the class, you get the linker error. Much like a normal linker error, it's because the compiler knew what you were talking about, but the linker couldn't find the definition. It's just got a very difficult to understand message.

mgiuca