How many instances are there of static data declar

2019-04-02 11:27发布

I'm working on compiling Cppcheck on AIX using xlC. Every checker class is derived from a Check class, whose constructor is responsible for registering that type of checker in a global static list.

Here's the relevant part of the code in question (filenames link to full source on Github):

check.h

class Check {
public:
    Check() {
        instances().push_back(this);
        instances().sort();
    }
    static std::list<Check *> &instances() {
        static std::list<Check *> _instances;
        return _instances;
    }
    // ...
};

checkbufferoverrun.h

class CheckBufferOverrun: public Check {
    // ...
};

checkbufferoverrun.cpp

// Register this check class (by creating a static instance of it)
namespace
{
CheckBufferOverrun instance;
}

Notice how the _instances static variable is declared inside a static function in the header file (there is no corresponding check.cpp file). When compiled with g++, the compiler and linker work together to ensure that there is only one implementation of the static instances() function, and therefore only one instance of the static _instances list. All the different checker classes instantiated in different .cpp files get registered in the same _instances list together.

However, under AIX's xlC, this same code ends up creating a different instances() function for every .cpp file in which it is included, which each having a different static _instances list. So there is no longer a single central _instances list, which causes Cppcheck to not run most of its checks.

Which compiler's behaviour is correct in this case?

Update: This question is not about how to fix the problem, I've already done that. I'm curious about which behaviour is correct.

标签: c++ static
3条回答
干净又极端
2楼-- · 2019-04-02 11:37

Correct it to:

   static std::list<Check *>& instances();

// check.cpp
 std::list<Check *> & Check::instances()
 {
     static std::list<Check *> _instances;
     return _instances;
 }

If you inline the function in the header file, each compilation unit will initially compile its own definition. However at link-time they should be reduced to one instance because of the One-Definition Rule.

I am sure you are aware, of course, that your constructor to Check is not thread-safe. Your singleton constructor is also not totally thread-safe because although the ODR ensures the threads between them can only create one instance, the constructor of list is not atomic and therefore I am not sure it is guaranteed to be completely constructed before the other thread sees it.

For a totally thread-safe way of constructing singletons or non-atomic statics, you can use boost::once.

查看更多
不美不萌又怎样
3楼-- · 2019-04-02 11:39

g++ has the correct behavior: there should be exactly one instance of the object. The C++ Standard says (C++03 7.1.2/4):

A static local variable in an extern inline function always refers to the same object.

Because the class has external linkage, the static member function also has external linkage, per C++03 3.5/5:

a member function...has external linkage if the name of the class has external linkage.

Because the member function is defined in the class definition, it is an inline function, per C++03 7.1.2/3:

A function defined within a class definition is an inline function.

查看更多
相关推荐>>
4楼-- · 2019-04-02 11:42

In this particular case g++ is correct (assuming that the instances() static member function returns a reference, that is a typo, right?). You might want to move the definition of the instances() function to a cpp file, that should be a work around in xlc.

查看更多
登录 后发表回答