我发布了一个继承自QEvent使用的自定义事件QCoreApplication::postEvent.我曾经读过,在使用postEvent它时需要有堆分配的事件.但我不确定谁有责任释放它.
所以,我试着用std::shared_ptr.但是,当我创建我的事件时std::shared_ptr,我收到此错误:
double free or corruption (fasttop)
Run Code Online (Sandbox Code Playgroud)
这是否意味着QEvent可以自由地释放事件,以便我可以创建事件而不必费心删除它?
这是代码的样子:
class MyCustomEvent : public QEvent {...}
std::shared_ptr<MyCustomEvent> evt(new MyCustomEvent(arg1, arg2)); // double free or corruption!
QCoreApplication::postEvent(targetObj, evt.get());
Run Code Online (Sandbox Code Playgroud)
从以下文档QCoreApplication::postEvent:
必须在堆上分配事件,因为事件后事件队列将获取事件的所有权并在发布后将其删除.发布后访问该事件是不安全的.
因此std::shared_ptr,在发布后维护事件是不正确的,因为帖子将事件的所有权转移到队列中.
一个安全的方法是将事件保存在std::unique_ptr(最好是std::make_unique),然后release在发布事件时调用它.这样,如果在帖子之前抛出异常,您可以确保将释放资源,并且您不会执行双重释放.您不一定需要使用智能指针,特别是在这么简单的情况下,但我认为在维护期间尝试保持内存所有权异常安全是A Good Thing™.
// C++14 idiomatic exception-safe event posting in Qt
auto evt = std::make_unique<MyCustomEvent>(arg1, arg2);
// intervening code that could throw
QCoreApplication::postEvent(targetObj, evt.release());
// C++11 idiomatic exception-safe event posting in Qt
std::unique_ptr<MyCustomEvent> evt { new MyCustomEvent(arg1, arg2) };
// intervening code that could throw
QCoreApplication::postEvent(targetObj, evt.release());
// C++98 idiomatic exception-safe event posting in Qt
QScopedPointer<MyCustomEvent> evt (new MyCustomEvent(arg1, arg2));
// intervening code that could throw
QCoreApplication::postEvent(targetObj, evt.take());
Run Code Online (Sandbox Code Playgroud)