Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't this create multiple defined symbols in this static library?

In a static library project, I have a header file with declared but not implemented functions.

I have a .cpp file that implements these functions.

Then, to better understand linker errors, I copied the cpp file so I have an exact duplicate of it that also gets compiled. So, both files have double implementations for every symbol in the header.

It compiles, and when used in another project, it links.

Here a minimum example for static library:

api.hpp:

void printWhatever();

errortest.cpp and duplicate.cpp are identical:

#include "api.hpp"
#include <iostream>
void printWhatever(){
  std::cout << "hi " << "\n";
}

I compile this as a static library with these 2 source files. I see the compiler produce reports for both files.

Now I use this compiled library in an executable, a different project: main.cpp:

#include <api.hpp>
int main(int argc, const char * argv[]) {
  printWhatever();

  return 0;
}

It runs and prints "hi".

Why is there not a multiple definition for the function?

like image 864
Jerome Baldridge Avatar asked Jun 16 '16 13:06

Jerome Baldridge


2 Answers

The key fact that was added to this question is the fact that the two modules with the duplicate symbol were linked into a static library.

A static library works very different than a shared library. When linking, the linker searches static libraries for referenced symbols. The first module that defines the referenced symbol gets linked to produce the final executable. The fact that another module defines the same symbol is irrelevant. If the other module with the duplicate symbol does not define any other symbol that the executable needs it does not get linked into the executable.

If you want to see a duplicate error with static libraries:

Call foo() and bar() from your main().

Define foo() and baz() in the 1st module in the static library.

Define bar() and baz() in the 2nd module in the static library.

Because both modules contain symbols referenced from main(), they are forced into getting linked with the executable, resulting in a duplicate symbol error due to baz().

like image 89
Sam Varshavchik Avatar answered Sep 28 '22 01:09

Sam Varshavchik


How to create a multiple defined symbols linking error

Quite minimal shell program to generate a quite minimal ill-formed C++ program that violates one definition rule:

echo 'int main(){}' | tee a.cpp > b.cpp
g++ a.cpp b.cpp

It should be easy to follow what's going on. There are two source files that both define a non-inline function int main(), thereby violating odr.

like image 40
eerorika Avatar answered Sep 28 '22 00:09

eerorika