Howto: Prevent the linker from removing unused static objects.
- or -
Using static objects to automatically register modules in a plug-in architecture.
- create a class auto_registrar that calls a ‘RegisterPluging’ function in its constructor.
- create a static object of this class and pass a pointer to a plugin instance to its constructor.
- prevent the linker from removing this seemingly unused static object, so that the constructor is called even if no code is actually doing anything with the object.
This article assumes that you are using MS-Windows and that your linker has an optimizer that removes unused objects. The general idea should apply to other OS as well.
You have written a generic class wxImage, which is able to load and save any kind of graphical image from/to a file. wxImage relies on a list of plug-in ‘handlers’ that do the actual loading/saving of the image. When it tries to
open a file, it searches this list of ‘handlers’ until it finds one that is capable of loading the image.
You have written five handlers, one for BMP, JPG, TIFF, PCX and TARGA. To use them, they must be ‘registered’ with the wxImage class and inserted into the list of handlers.
To automate this, you create a class auto_register
extern BmpHandler bmpHandler;
static auto_register ___register_bmp(&bmpHandler);
This works fine as long as you are building a ‘Debug’ build. The static object ___register_bmp is constructed at startup and its constructor calls wxImage::RegisterHandler with a pointer to the handler.
But when you build a ‘Release’ version of the program, the BmpHandler is not registered. The auto_register constructor is never called.
The linker is smart enough to detect that the object ___register_bmp is never used by the program. In a release build it
optimizes the code and removes all unused objects and functions. As a side effect, the constructor is never called and the BmpHandler is never registered.
This puts the burden of registering the handler on the user of the wxImage class. Somewhere, before the first image is loaded, the programmer using wxImage must make that call to wxImage::RegisterHandler and register the BmpHandler.
The linker will remove only those objects that are unused by the program. To be able to use the auto_register method to automatically registering the BmpHandler you have to interfere with the linkers ‘unused’ detection algorithm. Your
program must ‘use’ the ___register_bmp object, so that the linker will leave it alone.
To do so, take a pointer to the ___register_bmp object and do something with it. This is important. Just assigning it to a local variable in a function is not enough, because the compiler will optimize the code and throw out the local
variable if it is unused, which in turn removes the ‘take a pointer’ command and the linker will still think the object can be removed.
If you are creating a DLL (dynamic link library), then the easiest way to ‘use’ the object is to define a new function that returns the pointer and export it from the DLL. If you don’t export it, the linker will assume it is unused and
remove the function and the static object. Since you need to ‘use’ every auto_register object, you need one exported
function for every object. The best place to define the function is in the class you want to register. In the example this is the class BmpHandler.
class _declspec(dllexport) BmpHandler
// lots of code
// pseudo ‘use’ function
const auto_registrar *get_registrar() const
If you don’t like to actually give the pointer to the registrar object away, just cast it to long or do something else with it, as long as it prevents the compiler from optimizing the statement away.