Chinaunix首页 | 论坛 | 博客
  • 博客访问: 192508
  • 博文数量: 111
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 1240
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-07 07:46
文章分类

全部博文(111)

文章存档

2015年(2)

2014年(1)

2011年(1)

2010年(7)

2009年(100)

我的朋友

分类: LINUX

2009-08-19 07:23:44


转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静

引用计数是控制对象生命周期常用的手法,对象初始引用计数为一,引用一次计数加一,反引用一次计数减一,直到计数降为零时,对象被销毁。GObject也 实现了引用计数机制,g_object_ref函数用于引用,增加引用计数。g_object_unref函数用于反引用,减少引用计数。

GObject还提供了另外两个函数: g_object_weak_ref/g_object_weak_unref。weak_ref直译过来是弱引用,但它们的意义并不是很直观,新手常常很迷惑,本文介绍它们的意义和用途。我们先看看它们的函数原型:

void        g_object_weak_ref             (GObject        *object,

GWeakNotify notify,

gpointer data);

void g_object_weak_unref (GObject *object,

GWeakNotify notify,

gpointer data);

与g_object_ref/g_object_unref相比,g_object_weak_ref/g_object_weak_unref的 原型要复杂许多,而且也看不出它们与引用有何关系。但从文档和代码可以很容易知道,g_object_weak_ref的功能就是注册一个回调函数,该函 数将在对象被销毁时调用。

这与引用有什么关系呢?我们用一个例子说明:

在短信应用中,假设我们只允许一个写短信的窗口存在。要进入写短信界面,第一次创建写短信窗口,并把窗口句柄保存起来。这相当于引用了该窗口,但是我们不能调用g_object_ref去增加窗口的引用计数,原因是没适当的时候去反引用它,这会导致窗口无法关闭。

第二次进入时,先判断保存的窗口句柄是否为空,如果不为空,则认为窗口已经打开,直接把它提到前面来即可。

窗口不存在就创建它,存在就重用它,保证只有一个写短信的窗口存在。但上面的逻辑是有漏洞的:假设写完短信,用户通过正当或者不正当的手段关闭该窗 口。窗口已经关闭了,但外面还保存着它的句柄,这个窗口句柄指向无效的内存,若仅仅以保存的窗口句柄是否为空,来判断窗口是否已经打开,就必然会出现错 误。

窗口本身并不知道外面是否保存了它的句柄,它不可能在销毁时去把保存的句柄置为空。怎么办呢?最简单的办法就利用g_object_weak_ref,向窗口注册一个回调函数,窗口在销毁时调用该回调函数,在回调函数中,可以把保存的窗口句柄置为空。

简单的说:g_object_weak_ref让引用者有机会知道,引用的对象是否已经无效了,这可以防止野指针的出现。对于窗口对象,要模拟实现 g_object_weak_ref的功能,其实有好几种方法:比如用GTK_IS_WIDGET判断窗口是否还有效、用 g_object_set_data_full注册回调函数,或者注册GtkObject的destroy信号等。当然,只有 g_object_weak_ref是名正言顺的,也只有它是最简单的。

阅读(438) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~