QStates的内存管理添加到QStateMachine

Viv*_*ran 2 c++ qt state state-machine

以下代码导致内存损坏导致崩溃.我假设这是因为delete pTestStateMachine试图删除未在堆中分配的内存.那是对的吗?

如果是这样,是否意味着QStateMachine::addState(QAbstractState * state)必须始终传递动态分配的内存?不幸的是Qt docs并没有指定任何这样的条件.我在这里错过了什么?

class CTestClass
{
public:
    QState m_pTestState;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QStateMachine *pTestStateMachine;
    CTestClass  TestClass;

    pTestStateMachine = new QStateMachine();
    pTestStateMachine->addState(&(TestClass.m_pTestState));
    pTestStateMachine->setInitialState(&(TestClass.m_pTestState));
    pTestStateMachine->start();

    pTestStateMachine->stop();
    delete pTestStateMachine;

    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 6

它是否意味着QStateMachine::addState(QAbstractState * state)必须始终传递动态分配的内存?

一点也不.这QState在任何方面都不是特别的,同样的警告适用于任何QObject.回想一下,它QObject是其他QObjects 的容器:它拥有它们,除非它们先被单独销毁,否则将尝试使用delete子对象QObject::~QObject.

您的代码可以通过多种方式修复 - 在所有情况下,目标都不是让~QObject删除子状态不应该删除.

如果你让编译器完成它本应该做的工作,那一切都变得非常简单.使用原始拥有指针而不是在定义时初始化它们的代码风格是非惯用的,并且经常激发您遇到的错误.如果您有一个拥有指针,请使用std::unique_ptrQScopedPointer.delete和手动内存管理仅属于单用途资源管理类.它根本不属于通用代码:认为每个显式delete都是一个bug.你不需要它们.

class CTestClass
{
public:
  QState m_pTestState;
};

// Fix 1: Don't mix automatic storage duration with dynamic storage duration
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  {
    QStateMachine TestStateMachine;
    CTestClass    TestClass;
    TestStateMachine.addState(&TestClass.m_pTestState);
    TestStateMachine.setInitialState(&TestClass.m_pTestState);
    TestStateMachine.start();
    TestStateMachine.stop();
  } // <-- here the compiler emits
    // TestClass.~TestClass()
    // ...
    // TestStateMachine.~QStateMachine()
    //   ...
    //   TestStateMachine.~QObject()
}

// Fix 2: Make sure that the child doesn't outlive the parent.
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  {
    QScopedPointer<QStateMachine> TestStateMachine(new QStateMachine);
    CTestClass                    TestClass;
    TestStateMachine->addState(&TestClass.m_pTestState);
    TestStateMachine->setInitialState(&TestClass.m_pTestState);
    TestStateMachine->start();
    TestStateMachine->stop();
  } // <-- here the compiler emits
    // TestClass.~TestClass()
    // ...
    // TestStateMachine.~QScopedPointer()
    // delete data;
    //   data->~QStateMachine
    //   ...
    //   data->~QObject
    //   free(data)
}
Run Code Online (Sandbox Code Playgroud)