QStates 的内存管理添加到 QStateMachine
Memory management of QStates added to QStateMachine
以下代码由于内存损坏导致崩溃。我假设这是因为 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();
}
来自文档的措辞
If the state is already in a different machine, it will first be removed from its old machine, and then added to this machine.
QStateMachine
取得 QState
的所有权,这意味着它将尝试删除它在销毁时拥有的所有状态,您可以传递一个动态分配的指针,也可以使用 QStateMachine::removeState()
其中:
Removes the given state from this state machine. The state machine releases ownership of the state.
所以这应该有效:
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();
}
does it imply that QStateMachine::addState(QAbstractState * state)
must always be passed an dynamically allocated memory?
完全没有。 QState
没有任何特殊之处,同样的警告适用于任何 QObject
。回想一下 QObject
是其他 QObject
的容器:它拥有它们,除非它们先被单独销毁,否则将尝试 delete
QObject::~QObject
中的子对象。
您的代码可以通过多种方式修复 - 在所有情况下,objective 不会让 ~QObject
删除不应删除的子状态。
如果让编译器完成它应该做的工作,一切都会变得非常简单。您使用原始拥有指针而不是在定义点初始化它们的代码风格是非惯用的,并且经常会激发您 运行 遇到的错误。如果您有拥有指针,请使用 std::unique_ptr
或 QScopedPointer
。 delete
和手动内存管理仅属于单一用途的资源管理 class。它根本不属于通用代码:将每个显式 delete
视为一个错误。你不需要它们。
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)
}
以下代码由于内存损坏导致崩溃。我假设这是因为 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();
}
来自文档的措辞
If the state is already in a different machine, it will first be removed from its old machine, and then added to this machine.
QStateMachine
取得 QState
的所有权,这意味着它将尝试删除它在销毁时拥有的所有状态,您可以传递一个动态分配的指针,也可以使用 QStateMachine::removeState()
其中:
Removes the given state from this state machine. The state machine releases ownership of the state.
所以这应该有效:
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();
}
does it imply that
QStateMachine::addState(QAbstractState * state)
must always be passed an dynamically allocated memory?
完全没有。 QState
没有任何特殊之处,同样的警告适用于任何 QObject
。回想一下 QObject
是其他 QObject
的容器:它拥有它们,除非它们先被单独销毁,否则将尝试 delete
QObject::~QObject
中的子对象。
您的代码可以通过多种方式修复 - 在所有情况下,objective 不会让 ~QObject
删除不应删除的子状态。
如果让编译器完成它应该做的工作,一切都会变得非常简单。您使用原始拥有指针而不是在定义点初始化它们的代码风格是非惯用的,并且经常会激发您 运行 遇到的错误。如果您有拥有指针,请使用 std::unique_ptr
或 QScopedPointer
。 delete
和手动内存管理仅属于单一用途的资源管理 class。它根本不属于通用代码:将每个显式 delete
视为一个错误。你不需要它们。
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)
}