Multiple definition within static library
Asked Answered
T

1

6

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?
Tomahawk answered 4/10, 2019 at 16:13 Comment(4)
"...One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined...." source: en.cppreference.com/w/cpp/language/definitionSailmaker
@RichardCritten The is long and clear enough to be an answer.Dastardly
@KaenbyouRin feel bad about making it into an answer because it's really just a link.Sailmaker
It is undefined which of the two equivalent functions (files) from the archive will be used, but only one of them will be used if the only defined function in the object files is testfunc(). There is no way to predict. The symbol table added will list both files as defining the function. It is likely but not guaranteed that the first file in the archive is the one that'll be used. If you don't like the uncertainty, don't do it If the object files define other functions, there is a chance that you might get doubly defined errors, but it depends on what calls (and defines) those functions.Auspicious
L
5

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.

Lute answered 4/10, 2019 at 16:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.