首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QStates添加到QStateMachine中的内存管理

QStates添加到QStateMachine中的内存管理
EN

Stack Overflow用户
提问于 2015-10-13 17:28:51
回答 2查看 931关注 0票数 2

以下代码由于内存损坏而导致崩溃。我假设这是因为delete pTestStateMachine试图删除堆中没有分配的内存。对吗?

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

代码语言:javascript
复制
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();
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-13 18:18:24

这是否意味着必须始终传递一个动态分配的内存?

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

您的代码可以通过几种方式修复--在所有情况下,目标都不是让~QObject删除它不应该删除的子语句。

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

代码语言:javascript
复制
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)
}
票数 6
EN

Stack Overflow用户

发布于 2015-10-13 17:52:55

从文档的措辞

如果状态已经位于另一台机器中,则将首先从旧机器中移除状态,然后将其添加到此计算机中。

QStateMachine拥有QState的所有权,这意味着它将尝试删除它在销毁时所拥有的所有状态,您可以传递一个动态分配的指针,也可以使用QStateMachine::removeState()

从此状态机中移除给定状态。状态机释放州的所有权。

所以这应该是可行的:

代码语言:javascript
复制
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();
    pTestStateMachine->removeState(&(TestClass.m_pTestState)); //removing state before deletion
    delete pTestStateMachine;

    return a.exec();
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33108963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档