Я наткнулся на интересное явление, исследуя конструкторы разделяемых библиотек. Если у меня есть программа, которая ссылается на несколько общих библиотек, и у каждой библиотеки есть свой собственный конструктор, если все конструкторы имеют одинаковое имя функции, только конструктор одной библиотеки будет вызываться несколько раз, а не конструктор каждой библиотеки вызывается один раз.
Вот минимальный пример:
foo.h
#pragma once
void foo();
foo. c
#include <stdio.h>
#include "foo.h"
void foo() {};
void __attribute__((constructor)) init()
{
printf("foo init\n");
}
бар.ч
#pragma once
void bar();
бар. c
#include <stdio.h>
#include "bar.h"
void bar() {};
void __attribute__((constructor)) init()
{
printf("bar init\n");
}
основной. c
#include <stdio.h>
#include "foo.h"
#include "bar.h"
int main()
{
foo();
bar();
return 0;
}
Компиляция:
gcc -o libfoo.so foo.c -fPIC -shared
gcc -o libbar.so bar.c -fPIC -shared
gcc -o main main.c -lfoo -lbar -L.
Теперь, если я запускаю main
, я получаю:
foo init
foo init
Я ожидаю увидеть один foo init
и один bar init
при вызове конструктора каждой библиотеки, но вместо этого конструктор foo
вызывается дважды. Также интересно то, что если я поменяю порядок библиотек на последнем этапе компиляции на
gcc -o main main.c -lbar -lfoo -L.
Вывод, который я получу, будет
bar init
bar init
Я могу исправить это, изменив одно из следующих значений: имена функций конструктора, чтобы сделать их уникальными. Я также должен отметить, что это происходит независимо от имени функции, при условии, что они названы одинаково в обеих библиотеках.
Мой вопрос: почему это происходит в первую очередь? Я предполагаю, что это происходит из-за конфликта имен, но я точно не понимаю, что происходит.
Я тестировал, используя g cc 4.8.4 в Ubuntu 14.04.5 LTS, а также g cc 7.4.0 в Ubuntu 18.04.2 LTS в WSL.