QObject的销毁 [英] Destruction of QObjects

查看:242
本文介绍了QObject的销毁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序有时会在主函数的最后一条语句中给出分段错误。

My program sometimes gives Segmentation Fault at the last statement in main function.

返回a.exec();

我认为问题在于销毁顺序。 Qt文档表示

I think problem is with order of destruction. Qt documentation says that


无论销毁顺序如何,均不会删除两次QObject。

No QObject is deleted twice, regardless of the order of destruction.

但是当我尝试以下代码时

But when I tried following code it gives segmentation fault.

QWidget* first = new QWidget;
QWidget* second = new QWidget(first);
delete first;
delete second;

我知道什么时候删除 first 时,它会删除其子

I know when first is deleted, it deletes its children second also.

那么文档为什么说销毁顺序没有关系?

So why does Documentation says that order of destruction doesn't matter?

我们是否总是要小心删除子对象?

Should we be always careful about deleting child object?

我正在使用QNetworkAccessManager下载文件,文件下载完成后,我想删除 Downloader QObject 的$ c>对象以释放内存。但是,如果删除它,则会导致分段错误。

I am downloading a file with QNetworkAccessManager, when file download is completed I want to delete Downloader object which inherits QObject to free memory. But if I delete it causes segmentation fault.

推荐答案


那为什么文档说明了销毁顺序没关系吗?

So why does Documentation says that order of destruction doesn't matter?

这意味着您不需要手动删除对象。 Qt将在父/子层次结构中注册对象,并在必要时将其杀死。

It means that you don't NEED to delete objects manually. Qt will register object within parent/child hierarchy and kill it when necessary.

当然,它无法跟踪您可能存储在某处的所有指针。因此,如果您使用指向对象的指针,然后删除对象的父对象,然后尝试删除所使用的指针,那完全是您的错。

Of course, it can't track all pointers you might have stored somewhere. So if you take a pointer to object, then delete object's parent, then attempt to delete pointer you took, that'll be entirely your fault.


删除子对象时我们应该始终小心吗?

Should we be always careful about deleting child object?

否。删除子对象时,它将从其父对象中注销。
如果删除,然后删除第一,程序将正常运行。
因此,您应该记住,一旦杀死一个对象,它的所有子对象都消失了。

No. When you delete child object it will unregister itself from its parent. If you delete second, then delete first, program will work fine. So you should remember that once you killed an object all its children are gone.

顺便说一句,Qt具有 QPointer 类专门针对这种情况而设计,因此应使用它而不是原始指针。 QPointer 在指向的对象被销毁时会将自身设置为零。

By the way, Qt has QPointer class made specifically for this situation, so you should use it instead of raw pointers. QPointer will set itself to zero when object it points to is destroyed.


但是如果我删除它,则会导致分段错误。

But if I delete it causes segmentation fault.

这意味着您的程序存在尚未修复的错误。而且很可能(98%的可能性),该错误位于您的代码内,而不是Qt的错。

It means that your program has a bug you haven't fixed. And most likely (98% possibility) the bug is within your code, and is not Qt's fault. Debug the segfault and see where it happens.

解释

QWidget* first = new QWidget;
QWidget* second = new QWidget(first);
delete first;
delete second;

先删除 也会删除 second ,因为 second 是其子级。
但是,指针 second 不会自动更新。它会变成悬空的指针(指向不再存在的对象),并尝试删除它,将触发未定义的行为,在您的情况下,将使程序崩溃。

When you delete first it also deletes second, because second is its child. However, your pointer second will not be automatically updated. It'll turn into dangling pointer (points at object that is no longer there), and attempt to delete it, will trigger undefined behavior, which, in your case, will crash the program.

如果您 INSIST 秒内保持单独的指针 并且并删除再次),您可以使用类似的方法(不要忘记 #include< QPointer> ):

If you INSIST on keeping separate pointer for second AND deleting second after first (again), you can use something like this (don't forget to #include <QPointer>):

QPointer<QWidget> first = new QWidget,
    second = new QWidget(first);
delete first;
delete second;

但是,并没有真正的需要,通常人们只是这样做:

However, there's no real need for that, and normally people simply do this:

QWidget *first = new QWidget,
    *second = new QWidget(first);
delete first;//second is deleted automatically






通常,在C ++中,您必须手动自己删除分配的每个对象(带有 new )。这很容易出错,需要您编写析构函数,有时您可能会忘记它,这将导致内存泄漏。
但是,QObject会自动删除其析构函数中的所有子项,这意味着完全可以这样做:


Normally, in C++ you have to delete every object you allocated (with new) yourself, manually. This is error-prone, requires you to write a destructor, and you might somemetimes forget about it, which will result in memory leak. However, QObject automatically deletes all its children within its destructor, which means it is perfectly okay to do this:

 QObject *a = new QObject();
 QObject *b = new QObject(a);
 b = new QObject(a);
 b = new QObject(a);

只要您记得删除顶层对象,它的所有子资源都将自动释放。

As long as you remember to delete top-level object, all its child resources will be automatically freed.

但是,Qt无法跟踪您存储的指针。因此,如果您执行以下操作:

However, Qt cannot track pointers you stored. So if you do something like this:

QObject *a = new QObject(), *b = a;
delete a;

它不会更新现有的原始指针。顺便说一下,这是标准的C ++行为。

It will not update existing raw pointers. That's standard C++ behavior, by the way.

这就是QPointers的目的:

That's what QPointers are for:

QObject *a = new QObject(), *b = a;
QPointer<QObject> c = a;
delete a; 
//at this point c is set to zero. a and b  still point at previous object locations.

这篇关于QObject的销毁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆