原文:http://library.gnome.org/devel/gobject/2.14/gobject-memory.html
GObject的内存管理相关的API有一点复杂,但是背后的主旨是相当简单的:它的目的是提供一个灵活的基于引用计数的、可以集成在使用或需要各种不同的内存管理模型(就像垃圾回收)的应用程序的模型。这些方法被用来操作它的引用数。
/* Refcounting */ gpointer g_object_ref (gpointer object); void g_object_unref (gpointer object); /* Weak References */ typedef void (*GWeakNotify) (gpointer data, GObject *where_the_object_was); void g_object_weak_ref (GObject *object, GWeakNotify notify, gpointer data); void g_object_weak_unref (GObject *object, GWeakNotify notify, gpointer data); void g_object_add_weak_pointer (GObject *object, gpointer *weak_pointer_location); void g_object_remove_weak_pointer (GObject *object, gpointer *weak_pointer_location); /* Cycle handling */ void g_object_run_dispose (GObject *object);
引用计数
函数g_object_ref/g_object_unref 分别增加或减少引用数。在GLib 2.8中,这些函数是线程安全的。所谓引用计数,没啥悬念的,当g_object_new初始化了一个实例后,调用者即成了新创建的引用的把持者。当引用计数到达0以后,最后保持这个对象引用的客户端在调用g_object_unref后,处理和终结类方法将被调用。
在终结函数被调用以后,g_type_free_instance被呼叫来翻译这个对象的实例。依赖内存分配策略中类型的注册时间(通过g_type_register函数集),对象的实例所占据的内存将被释放并将类型返回对象池中。一旦对象被释放,如果它是最后一个这个类型的实例,那么类型的类将被销毁(如前面章节所讲的销毁策略一样)。
关于一个GObject的销毁过程总结如下:
表格太大,不贴了。
弱引用
弱引用用来监视一个对象的终结:g_object_weak_ref加入了一个不把持对象引用的监视回调函数,但当对象运行它的处理函数时会被调用。这样的话,每个弱引用都可以在对象终结前被调用超过一次(因为处理函数在对象终结前会运行超过一次)。
g_object_weak_unref可以用来从对象上移除一个监视回调函数。
弱引用同样用来实现g_object_add_weak_pointer和g_object_remove_weak_pointer。这些函数用来废弃对象的指针,当对象被终结以后。
引用计数和周期
注意:下面的段落内容由 James Henstridge所启发。如果有任何表扬都应该给他。
GObject的内存管理模式被设计为可以容易地集成在现存的使用垃圾回收的代码中。这就是为什么销毁过程会被分离成两个阶段:第一个阶段,执行处理过程使得猜想释放了所有到其他对象的引用。第二个阶段,执行终结处理函数并猜想完成了对象销毁过程。对象的方法应该有能力在这两个阶段里无错误的情况下运行。
这两步走的销毁过程对于打断引用计数周期是十分有用的。当在外部代码检测循环周期时,外部代码可以调用g_object_dispose来运行与这个对象相关联的处理函数来理想地打断现存的周期。
聪明的读者可能已经懂了处理函数的一些规则:处理函数可以被调用好几次。我们来假设一个引用计数周期:对象A引用了B,同B自己也引用了对象A。现在我们知道了这个周期,并决定销毁这两个对象。来完成这个,只要在其中一个对象调用g_object_dispose即可。
如果对象A释放了到所有其他对象的引用,这个意味着它释放了它到对象B的引用。如果对象B已经不被其他所占有,这就是最后一次由B的处理函数进行的引用计数,释放在对象A上的引用。