我使用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());
答案 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());