Компоновщик загружает только те модули, которые он должен (т. Е. То, что вы на самом деле ссылаетесь неявно или явно ), если только вы не форсируете его.
Это и хорошая вещь и неудачная. Это ускоряет процесс линковки и предотвращает раздувание кода. Обычно это также не вызывает проблем, потому что обычно вы ссылаетесь на все модули, которые нужны каким-то образом, а то, на что вы не ссылаетесь, не нужно. Обычно.
Но это также является причиной этого тихого сбоя: компоновщик никогда не загружает модуль, содержащий ваши функции конструктора / деструктора, и никогда даже не смотрит на него . Это потому, что вы никогда не вызываете эти функции.
Вы можете заставить компоновщик включить модуль, явно связав его с объектным файлом, который соответствует источнику, содержащему функции конструктора / деструктора.
Другими словами, если функции конструктора / деструктора находятся в foo.c
, добавьте -l/path/to/foo.o
к параметрам своего компоновщика или просто передайте foo.o
в командной строке компоновщику (в качестве дополнительного аргумента).
В любом случае, делая это, вы явно указываете компоновщику, что нужно рассмотреть этот модуль, и он заставит его найти функции конструктора и правильно вызвать их.
Альтернативой (которая не требует, чтобы вы играли с командной строкой) может быть помещение переменной или функции (которая не обязательно что-либо делает) в тот же исходный файл, что и функции конструктора / деструктора, и вызов этой переменной из любого Исходный файл в основной программе.
Это также заставит компоновщик загрузить содержащий модуль (где он найдет функции конструктора).
Обновление:
Я протестировал эту альтернативу, она отлично работает:
/* libcode.c */
void enable_constructors() { /* do nothing */ }
void __attribute__ ((constructor)) con() { __builtin_puts("construct"); }
void __attribute__ ((destructor)) des() { __builtin_puts("destruct"); }
/* main.c */
extern void enable_constructors();
int main()
{
enable_constructors();
__builtin_puts("main");
return 0;
}
Вывод:
construct
main
destruct
Он также работает с глобальной переменной, к которой вы прикоснулись из исходного файла основной программы:
/* libcode.c */
int enable_constructors; /* not used for anything */
void __attribute__ ((constructor)) cons() { __builtin_puts("construct"); }
void __attribute__ ((destructor)) des() { __builtin_puts("destruct"); }
/* main.c */
extern int enable_constructors;
int main()
{
++enable_constructors; /* touch the other module */
__builtin_puts("main");
return 0;
}