Is there any way to make a function get called just by linking its .o file?
For example:
foo.cpp:
extern int x;
void f() { x = 42; }
struct T { T() { f(); } } t; // we use constructor of global
// object to call f during initialization
bar.cpp:
#include <iostream>
int x;
int main()
{
std::cout << x;
}
To compile/link/run:
$ g++ -c foo.cpp
$ g++ -c bar.cpp
$ g++ foo.o bar.o
$ ./a.out
42
This seems to work with gcc 4.7. It outputs 42 as expected. However I remember on some old compilers I had a problem with this pattern that because nothing was really “using” foo.o it was optimized out at link time. (perhaps this particular example is not representative of the problem for some reason)
What does the C++11 standard have to say about this pattern? Is it guaranteed to work?
I believe you’re not off the hook. The standard doesn’t guarantee that your code works as intended, although many people rely on that behaviour for various “self-registering” constructions.
Your object
tis dynamically initialized, which has the side effect of callingf. The standard has this to say about dynamic initialization of statically-stored objects (3.6.2/4, “Initialization of non-local variables”):In your code, only
xis odr-used, butxis defined in the main translation unit. No variable or function from the other TU is odr-used in your program, so technically there is no guarantee thattwill ever be initialized. Technically, something from every TU must be referred to by the static control flow of your program in order for everything to be initialized.As I said, there’s lots of real-world code out there with “self-registering” translation units (which for example register a factory function pointer in a string-keyed map), so that by simply adding TUs to the final program you end up with more functionality. I’m told that most compilers will unconditionally initialize all global variables just because not doing so would break a lot of real-world code. But don’t rely on it!