以下代码是抛出 SIGSEGV 还是按预期工作取决于目标文件在 makefile 中出现的顺序(在我的例子中是 .pro)。我不是很有信心只需要按正确的顺序维护它们。是否对我的源代码进行了简单的更改,从而消除了对目标文件正确顺序的依赖?
这些是源文件,归结为一个简短的例子。
dummy0.h
:
#ifndef DUMMY0_H
#define DUMMY0_H
#include <QObject>
class Dummy0 : public QObject
{
Q_OBJECT
public:
explicit Dummy0(QObject *parent = 0);
};
#endif // DUMMY0_H
dummy0.cpp
:
#include "dummy0.h"
#include "unittestclass.h"
Dummy0::Dummy0(QObject *parent) : QObject(parent) {}
ADD_TEST( Dummy0 )
顾名思义,以后还会有Dummy1
... Dummy<n>
.
unittestclass.h
:
#ifndef UNITTESTCLASS_H
#define UNITTESTCLASS_H
#include <QObject>
#include <QTest>
#include <QDebug>
#include <memory>
#include <list>
// see https://stackoverflow.com/questions/12194256/qt-how-to-organize-unit-test-with-more-than-one-class
namespace TestCollector {
class BaseClass { // see https://hackernoon.com/shared-static-variable-for-all-template-class-instances-eaed385f332b
public:
BaseClass() = default;
int listClasses( int argc, char *argv[] );
protected:
static std::list<std::shared_ptr<QObject>> testlist;
};
template <class T>
class UnitTestClass : public BaseClass {
public:
UnitTestClass() {
std::shared_ptr<QObject> ptr = std::make_shared<T>();
qDebug() << "pushing a" << ptr.get()->metaObject()->className();
qDebug() << "testlist size before:" << testlist.size() << "of" << testlist.max_size();
testlist.size(); // no SIGSEGV !?
testlist.push_back( ptr ); // SIGSEGV here when race condition
qDebug() << "testlist size after:" << testlist.size();
}
};
} // TestCollector
#define ADD_TEST(className) static TestCollector::UnitTestClass<className> test;
#endif // UNITTESTCLASS_H
unittestclass.cpp
:
#include "unittestclass.h"
namespace TestCollector {
std::list<std::shared_ptr<QObject>> BaseClass::testlist;
int BaseClass::listClasses( int argc, char *argv[] ) {
int result=0;
for( const auto c : testlist ) {
qDebug() << "got" << c.get()->metaObject()->className();
}
return result;
}
} // TestCollector
main.cpp
:
#include "unittestclass.h"
int main(int argc, char *argv[]) {
TestCollector::BaseClass base;
return base.listClasses( argc, argv );
}
当我有 dummy0.cpp
之前unittestclass.cpp
程序在 testlist.push_back(ptr)
处失败[注意:有趣的是,testlist.size()
在 push_back
之前的行中不会失败]。当dummy0.cpp
后来出现,一切都很好。这暗示了一个问题,当目标文件的顺序不利时,可能会在初始化之前使用 teSTList!?
如何避免依赖于此顺序?
[我目前使用的是 c++11、QtCreator 3.5.1、g++5.4.0、GNU ld 2.26.1。]
最佳答案
您可以通过函数间接确保您所依赖的对象存在:
class BaseClass
{
// ...
// This returns a pointer only to make it hard to copy the list by mistake.
// Some people prefer to use a reference, and some prefer dynamic allocation.
// The important part is that the object is created the first time you use it.
static std::list<std::shared_ptr<QObject>>* get_testlist()
{
static std::list<std::shared_ptr<QObject>> tests;
return &tests;
}
};
然后像这样使用它:
UnitTestClass() {
std::shared_ptr<QObject> ptr = std::make_shared<T>();
qDebug() << "pushing a" << ptr.get()->metaObject()->className();
auto testlist = get_testlist();
qDebug() << "testlist size before:" << testlist->size() << "of" << testlist->max_size();
testlist->push_back( ptr );
qDebug() << "testlist size after:" << testlist->size();
}
关于c++ - 如何修复静态类成员的初始化顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54788022/