免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5524 | 回复: 6
打印 上一主题 下一主题

关于Gtk对象内存的管理? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-05 09:30 |只看该作者 |倒序浏览
初学者一个,在gtk。org看到了关于GtkObject的一段描述:
GtkObject is the base class for all widgets, and for a few non-widget objects such as GtkAdjustment. GtkObject predates GObject; non-widgets that derive from GtkObject rather than GObject do so for backward compatibility reasons.

GtkObjects are created with a "floating" reference count. This means that the initial reference is not owned by anyone. Calling g_object_unref() on a newly-created GtkObject is incorrect, the floating reference has to be removed first. This can be done by anyone at any time, by calling g_object_ref_sink() to convert the floating reference into a regular reference. g_object_ref_sink() returns a new reference if an object is already sunk (has no floating reference).

When you add a widget to its parent container, the parent container will do this:

  g_object_ref_sink (G_OBJECT (child_widget));

This means that the container now owns a reference to the child widget and the child widget has no floating reference.

The purpose of the floating reference is to keep the child widget alive until you add it to a parent container:

   button = gtk_button_new ();
   /* button has one floating reference to keep it alive */
   gtk_container_add (GTK_CONTAINER (container), button);
   /* button has one non-floating reference owned by the container */

GtkWindow is a special case, because GTK+ itself will ref/sink it on creation. That is, after calling gtk_window_new(), the GtkWindow will have one reference which is owned by GTK+, and no floating references.

One more factor comes into play: the "destroy" signal, emitted by the gtk_object_destroy() method. The "destroy" signal asks all code owning a reference to an object to release said reference. So, for example, if you call gtk_object_destroy() on a GtkWindow, GTK+ will release the reference count that it owns; if you call gtk_object_destroy() on a GtkButton, then the button will be removed from its parent container and the parent container will release its reference to the button. Because these references are released, calling gtk_object_destroy() should result in freeing all memory associated with an object, unless some buggy code fails to release its references in response to the "destroy" signal. Freeing memory (referred to as finalization only happens if the reference count reaches zero.

Some simple rules for handling ""

    *

      Never call g_object_unref() unless you have previously called g_object_ref(), even if you created the GtkObject. (Note: this is not true for GObject; for GObject, the creator of the object owns a reference.)
    *

      Call gtk_object_destroy() to get rid of most objects in most cases. In particular, widgets are almost always destroyed in this way.
    *

      Because of the floating reference count, you don't need to worry about reference counting for widgets and toplevel windows, unless you explicitly call g_object_ref() yourself.

1.对于GtkObject派生的子类,上面说我们不应该调用g_object_unref()除非之前用过g_object_ref,有没有例外呢?
2.对于从GObject派生的子类,如GtkAction, GtkUIManager,因为他们创建后不是floating的ref,是不是我们都应该用g_object_unref去释放对象的内存呢?
3.g_object_unref应该在什么时候正确的使用?
4.如果我对GObject派生的子类,不调用g_object_unref会不会导致内存泄漏?还是Gtk系统在你程序退出后都会做一次统一的清理?

初学者,对Gtk对象的释放使用比较疑惑,官网上并没有描述那些对象在create后需要你手动的去释放。还请老大们帮忙解答一下。
THX.

论坛徽章:
0
2 [报告]
发表于 2008-09-10 09:24 |只看该作者
1.对于GtkObject派生的子类,上面说我们不应该调用g_object_unref()除非之前用过g_object_ref,有没有例外呢?
应该有的,不过到现还没有碰到过。

2.对于从GObject派生的子类,如GtkAction, GtkUIManager,因为他们创建后不是floating的ref,是不是我们都应该用g_object_unref去释放对象的内存呢?
GTK的内部应该会维护的很好,应该不用担心。想确定的话,就看看源代码吧。

3.g_object_unref应该在什么时候正确的使用?
当你之前有过引用的时候,应该调用这个了。比如你自己创建一个能够多次使用的窗口,每一次引用以后,都要调用它。这个问题以前搞了很久,才有点明白。以前也不是很明白,不知道说的对不对,还请指教。

4.如果我对GObject派生的子类,不调用g_object_unref会不会导致内存泄漏?还是Gtk系统在你程序退出后都会做一次统一的清理?
我知道当你退出GTK+主循环时,它的资源应该被释放了,相当于一个进程或是一个线程取消后,资源被释放一样。

初学者,对Gtk对象的释放使用比较疑惑,官网上并没有描述那些对象在create后需要你手动的去释放。还请老大们帮忙解答一下。
THX.
偶也是初学,以多交流吧!

论坛徽章:
0
3 [报告]
发表于 2008-09-12 12:09 |只看该作者

回复 #2 pondra 的帖子

>>>
2.对于从GObject派生的子类,如GtkAction, GtkUIManager,因为他们创建后不是floating的ref,是不是我们都应该用g_object_unref去释放对象的内存呢?
GTK的内部应该会维护的很好,应该不用担心。想确定的话,就看看源代码吧。
<<<<<
这一点是需要释放的,当你创建了这些对象后,你就是owner,如果你不用,你需要显示的去unref释放对象。
而对于GtkObject,只要把对象加入到一个container你就可以不管了,最后destroy掉这个container的时候会释放他所包含的所有对象,不过没有加入到container的就不太清楚,但是官网上明确的说你不要显示的调用unref除非你曾经调用过ref,我想,一般不把一个对象加入到container的时候几乎没有,如果有还是需要你自己来管理,不过首先应该通过set_ref获取owner去掉对象的floating,然后就可以安全的调用unref了。
最近的一点理解。

论坛徽章:
0
4 [报告]
发表于 2008-09-13 11:29 |只看该作者
gtk_widget_destroy ()
void                gtk_widget_destroy                  (GtkWidget *widget);Destroys a widget. Equivalent to gtk_object_destroy(), except that you don't have to cast the widget to GtkObject. When a widget is destroyed, it will break any references it holds to other objects. If the widget is inside a container, the widget will be removed from the container. If the widget is a toplevel (derived from GtkWindow), it will be removed from the list of toplevels, and the reference GTK+ holds to it will be removed. Removing a widget from its container or the list of toplevels results in the widget being finalized, unless you've added additional references to the widget with g_object_ref().

In most cases, only toplevel widgets (windows) require explicit destruction, because when you destroy a toplevel its children will be destroyed as well.

这个我也看了很久,不过还是有些不太理解,Destroy后内存就被释放了吗,像你说的,把一个构件放到一个Container中,那销毁这个Container时,里面的构件也被销毁了吗?上面只是说被Remove了,只有是Toplevel的构件被销毁时才能把里面的了构件一并销毁。还是不太明白。

论坛徽章:
0
5 [报告]
发表于 2008-09-15 16:43 |只看该作者
都不需要自己释放内存吧。。
因为GUI对象在程序运行的时候始终是存在的,而且一般也不会在循环中创建控件吧。。
所以没必要关心销毁控件的事,进程一退出就什么都没了..
我觉得GTK中要注意内存的地方只有 gtk_tree_model_get .. 取字符串的时候gtk会给你自动复制一份。 而且要排序GtkTreeView会用到这个功能。。。循环里面泄漏内存量就非常大了

论坛徽章:
0
6 [报告]
发表于 2008-09-16 09:35 |只看该作者
原帖由 pondra 于 2008-9-13 11:29 发表
gtk_widget_destroy ()
void                gtk_widget_destroy                  (GtkWidget *widget);Destroys a widget. Equivalent to gtk_object_destroy(), except that you don't have to cast the wi ...

我的理解是destroy后,触发本控件被销毁,那么他的ref减1如果ref=0就说明该释放内存了,同时他会将所有加入到他的其他控件的ref--,如果=0也将释放内存,
如果不等0,那么控件还将存在,因为其他地方可能还存在对他的引用。没有看源码,所以也只是我的想法,可以对着源码看看。

论坛徽章:
0
7 [报告]
发表于 2008-09-16 09:39 |只看该作者
原帖由 rushrush 于 2008-9-15 16:43 发表
都不需要自己释放内存吧。。
因为GUI对象在程序运行的时候始终是存在的,而且一般也不会在循环中创建控件吧。。
所以没必要关心销毁控件的事,进程一退出就什么都没了..
我觉得GTK中要注意内存的地方只有  ...

我觉得不是的,所有直接从GObject派生的对象,你都需要unref一下。比如GtkUIManager,你可以在程序里试试,在你的main最后也就是在gtk_main()之后再unref一下这个对象,程序是不会出错的,因为你应该这样做,但是如果是从GtkObject派生的那些控件对象,那就是会报错,同时你也可以把引用计数的值打印出来看看。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP