Search code examples
c++linkerunix-ar

Multiple definition within static library


I have a question that is very closely related to Linker does not emit multiple definition error when same symbol coexists in object file and static library, but concerns a slightly different situation. Just like there, I have two .cpp files (say: test1.cpp and test2.cpp) each containing an implementation of the same function, i.e. void testfunc(). I also have a header file test.h where I declare testfunc, as well as a file main.cpp with a main function which contains a call to testfunc()like this:

include "test.h"
int main() {
    testfunc();
}

I compile the .cpp files separately by invoking g++ -c *.cpp and then create a static library out of them with ar rvs libtest.a test1.o test2.o. When linking main.o against the library now, the linker does not complain as I expected it to do:

gcc main.o -L. -ltest -o main

The resulting executable works perfectly fine - calling one of the two implementations of testfunc(). To be honest, I expected some error like multiple definition of... to occur. Therefore, my questions are:

  1. Why is this actually working - is the reason in ar, which only adds one of the two object files to the library, or does the library contain both object files & the reason for this behavior is rather to be found in the linking process, where the linker stops searching the lib after it found one definition of testfunc?
  2. Can I somehow influence which definition of testfunc is actually used or is this even defined? I.e., is it maybe the order of the arguments to ar deciding which one is used?
  3. Is this behavior the same for any linker/version of ar or might it be that this depends on the system?

Solution

  • A library is just a collection of object-files containing exported symbols. It may contain any number of duplicates (just like real book libraries may contain many books with the same title). There is no linking involved.

    When linking, generally speaking, the linker only looks at libraries in case there are unresolved symbols. When looking for those, it might find one and if it does it will look no further for that symbol.

    There may arise a conflict when it resolves another unresolved symbol found in another object file that contains a definition of an earlier found symbol; now it will generate an error of duplicate symbols.