以下代码由于内存损坏而导致崩溃。我假设这是因为delete pTestStateMachine试图删除堆中没有分配的内存。对吗?
如果是这样的话,这是否意味着QStateMachine::addState(QAbstractState * state)必须始终被传递一个动态分配的内存?不幸的是,Qt文档没有指定任何这样的条件。我在这里错过了什么?
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();
}发布于 2015-10-13 18:18:24
这是否意味着必须始终传递一个动态分配的内存?
不用谢。QState在任何方面都不是特别的,同样的警告也适用于任何QObject。回想一下,QObject是其他QObject的容器:它拥有它们,除非它们首先被单独销毁,否则将尝试在QObject::~QObject中对子对象进行delete。
您的代码可以通过几种方式修复--在所有情况下,目标都不是让~QObject删除它不应该删除的子语句。
如果让编译器完成它应该做的工作,一切都会变得非常简单。使用原始的拥有指针而不是在定义点初始化它们的代码风格是非惯用的,经常会激发您遇到的错误。如果您有一个拥有指针,请使用std::unique_ptr或QScopedPointer。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)
}发布于 2015-10-13 17:52:55
从文档的措辞
如果状态已经位于另一台机器中,则将首先从旧机器中移除状态,然后将其添加到此计算机中。
QStateMachine拥有QState的所有权,这意味着它将尝试删除它在销毁时所拥有的所有状态,您可以传递一个动态分配的指针,也可以使用QStateMachine::removeState():
从此状态机中移除给定状态。状态机释放州的所有权。
所以这应该是可行的:
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();
}https://stackoverflow.com/questions/33108963
复制相似问题