The linker only loads the modules it must (i.e. what you actually reference implicitly or explicitly), unless you force it.
That is both a good thing, and unfortunate. It makes the link process faster and prevents code bloat. It normally does not cause problems either, because normally you reference all modules that are needed in some way, and what you don't reference isn't needed. Normally.
But it is also the cause for this silent failure: The linker never loads the module containing your constructor/destructor functions and never even looks at it. That is because you never actually call these functions.
You can force the linker to include the module by explicitly linking with the object file that corresponds to the source containing the constructor/destructor functions.
In other words, if the constructor/destructor functions are in foo.c
, add -l/path/to/foo.o
to your linker's options, or simply pass foo.o
on the commandline to the linker (as an extra argument).
In either case, by doing so, you explicitly tell the linker to consider this module, and doing so will make it find the constructor functions and properly call them.
An alternative (which does not require you to play with the commandline) may be putting a variable or a function (which does not necessarily do anything) into the same source file as your constructor/destructor functions and calling that one from any source file in the main program.
This will also force the linker to load the containing module (where it will find the constructor functions).
Update:
I tested that alternative, it works fine:
/* 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;
}
Output is:
construct
main
destruct
It also works with a global variable which you touch from a source file in the main program:
/* 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;
}