ABu
ABu

Reputation: 12309

Object files, static libraries and one-definition rule

Let's imagine I have a compilation line like the following:

gcc <flags...> -o a.out obj1.o obj2.o

where both obj1.o and obj2.o defines void f(int). I will get a multiple-definition error (violation of the one-definition-rule).

Ok, now, imagine the following:

gcc <flags...> -o a.out obj1.o -lstatic_lib

where both obj1.o and static_lib.a defines f(int). I know that a static library is a concatenation of .o files, and for every symbol pending to be solved, is found inside any of the .o files of the static library, then the whole .o that resolves that symbol will be linked into the binary, together with any other symbol that very same .o provides.

That behaviour makes me wonder. Imagine that static_lib.a consists of two objects, static_obj1.o and static_obj2.o, where static_obj1.o is who defines f(int). Since obj1.o already defines f(int) as well, the linker is not looking for it within static_lib.a, and so static_obj1.o won't be theoretically included, but, and this is the question:

NOTE: I'm tagging both C and C++ because I guess the behaviour is the same for both in this regard. If it's not, please clarify, I'm very interested in knowing any behavioural difference. Also, if the behaviour is very different between gcc/clang/visual studio/linux/windows, please clarify. If the behaviour is roughly the same, then focus on gcc over linux.

Upvotes: 0

Views: 123

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 224536

Would the linker, after integrating static_obj1.o because of f2(int), issue a multiple definition warning because of f1(int) being now twice?

Yes.

… one-definition rule…

This is not governed by the one-definition rule in C++ or the corresponding rule in C. In regard to this linking issue, those rules merely indicate that a conforming program will not contain multiple definitions. They do not govern what happens when linking with multiple definitions. For example:

  • The linker could issue an error message and not produce an executable. This is conforming behavior because we interpret the program requested by linking these multiple object modules together to have multiple definitions. Then the behavior is not defined by the language standard, so any behavior is conforming.
  • Hypothetically, the linker could choose one object module and form an executable containing only one definition of each symbol. Again, since the behavior is not defined by the language standard, any behavior is conforming. Alternately, we could interpret the request to the linker to be a request to form a program with only one definition of the symbol, resulting in a program that does conform to the language standard. The standards are silent with regard to how we use linkers and other tools to link translation units together, so various interpretations of these interactions are possible.

Upvotes: 2

Related Questions