Finding C++ static initialization order problems

2018-12-31 15:45发布

We've run into some problems with the static initialization order fiasco, and I'm looking for ways to comb through a whole lot of code to find possible occurrences. Any suggestions on how to do this efficiently?

Edit: I'm getting some good answers on how to SOLVE the static initialization order problem, but that's not really my question. I'd like to know how to FIND objects that are subject to this problem. Evan's answer seems to be the best so far in this regard; I don't think we can use valgrind, but we may have memory analysis tools that could perform a similar function. That would catch problems only where the initialization order is wrong for a given build, and the order can change with each build. Perhaps there's a static analysis tool that would catch this. Our platform is IBM XLC/C++ compiler running on AIX.

11条回答
路过你的时光
2楼-- · 2018-12-31 16:20

Gimpel Software (www.gimpel.com) claims that their PC-Lint/FlexeLint static analysis tools will detect such problems.

I have had good experience with their tools, but not with this specific issue so I can't vouch for how much they would help.

查看更多
皆成旧梦
3楼-- · 2018-12-31 16:21

perhaps use valgrind to find usage of uninitialized memory. The nicest solution to the "static initialization order fiasco" is to use a static function which returns an instance of the object like this:

class A {
public:
    static X &getStatic() { static X my_static; return my_static; }
};

This way you access your static object is by calling getStatic, this will guarantee it is initialized on first use.

If you need to worry about order of de-initialization, return a new'd object instead of a statically allocated object.

EDIT: removed the redundant static object, i dunno why but i mixed and matched two methods of having a static together in my original example.

查看更多
闭嘴吧你
4楼-- · 2018-12-31 16:21

The first thing you need to do is make a list of all static objects that have non-trivial constructors.

Given that, you either need to plug through them one at a time, or simply replace them all with singleton-pattern objects.

The singleton pattern comes in for a lot of criticism, but the lazy "as-required" construction is a fairly easy way to fix the majority of the problems now and in the future.

old...

MyObject myObject

new...

MyObject &myObject()
{
  static MyObject myActualObject;
  return myActualObject;
}

Of course, if your application is multi-threaded, this can cause you more problems than you had in the first place...

查看更多
皆成旧梦
5楼-- · 2018-12-31 16:22

Depending on your compiler, you can place a breakpoint at the constructor initialization code. In Visual C++, this is the _initterm function, which is given a start and end pointer of a list of the functions to call.

Then step into each function to get the file and function name (assuming you've compiled with debugging info on). Once you have the names, step out of the function (back up to _initterm) and continue until _initterm exits.

That gives you all the static initializers, not just the ones in your code - it's the easiest way to get an exhaustive list. You can filter out the ones you have no control over (such as those in third-party libraries).

The theory holds for other compilers but the name of the function and the capability of the debugger may change.

查看更多
唯独是你
6楼-- · 2018-12-31 16:24

If your project is in Visual Studio (I've tried this with VC++ Express 2005, and with Visual Studio 2008 Pro):

  1. Open Class View (Main menu->View->Class View)
  2. Expand each project in your solution and Click on "Global Functions and Variables"

This should give you a decent list of all of the globals that are subject to the fiasco.

In the end, a better approach is to try to remove these objects from your project (easier said than done, sometimes).

查看更多
登录 后发表回答