postEvent是否在发布后释放了该事件? (双重免费或腐败)

时间:2015-09-15 09:58:18

标签: c++ qt

我使用QEvent发布了从QCoreApplication::postEvent继承的自定义事件。我曾经读过,当使用postEvent时,必须有堆分配的事件。但我不确定谁有责任解除这个。

所以,我尝试使用std::shared_ptr。但是,当我使用std::shared_ptr创建活动时,我收到了此错误:

double free or corruption (fasttop)

这是否意味着QEvent可以释放事件,这样我就可以创建事件而不用去删除它?

代码如下所示:

class MyCustomEvent : public QEvent {...}

std::shared_ptr<MyCustomEvent> evt(new MyCustomEvent(arg1, arg2)); // double free or corruption!
QCoreApplication::postEvent(targetObj, evt.get());

1 个答案:

答案 0 :(得分:5)

来自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());