Hacker News new | ask | show | jobs
by dale_glass 335 days ago
Oh, static linking can be lots of "fun". I ran into this interesting issue once.

1. We have libshared. It's got logging and other general stuff. libshared has static "Foo foo;" somewhere.

2. We link libshared into libfoo and libbar.

3. libfoo and libbar then go into application.

If you do this statically, what happens is that the Foo constructor gets invoked twice, once from libfoo and once from libbar. And also gets destroyed twice.

1 comments

But this is expected behaviour. The Linker cannot know about your intent but is "dumb" in that it only follows some simple rules. Both libfoo and libbar have their own copy of the .o from libshared containing the "Foo foo" instance. Thus the .init/.fini sections in libfoo and libbar make calls to the ctor/dtor of their own "Foo foo" instances resulting in the observed two calls in the app.

The way people generally solve this problem is by using a helper class in the library header file which does reference counting for proper initialization/destruction of a single global instance. For an example see std::ios_base::Init in the standard C++ library - https://en.cppreference.com/w/cpp/io/ios_base/Init

To understand the basics of how linking (both static and dynamic) works see;

1) Hongjiu Lu's ELF: From the Programmer's Perspective - https://ftp.math.utah.edu/u/ma/hohn/linux/misc/elf/elf.html

2) Ian Lance Taylor's 20-part linker essay on his blog; ToC here - https://lwn.net/Articles/276782/