何时取消具有浮动引用的GVariant?

时间:2015-04-15 23:16:00

标签: glib

https://developer.gnome.org/glib/unstable/glib-GVariant.html#g-variant-ref-sink

我已经阅读了上面的glib手册,上面写着:" GVariant使用浮动引用计数系统。名称以g_variant_new_开头的所有函数都返回浮动引用。"但浮动引用计数的实际描述在哪里?我无法找到它的全面描述。

特别是我想了解什么时候需要引用一个变体,何时不需要。例如:

GVariant *a_v = g_variant_new_boolean(TRUE);
GVariant *another_v = g_variant_new("v", a_v);
  1. 我认为我不需要引用a_v,因为它被第二个g_variant_new消耗。这是对的吗?
  2. 我是否需要引用another_v(假设another_v从那时起没有传递给其他任何内容?)
  3. 这在哪里记录? (我认为通过在搜索过程中找到的不同示例进行推断,我有正确的理解,但似乎无法找到明确说明这一点的官方glib文档。)

2 个答案:

答案 0 :(得分:8)

GObject参考手册中有一个关于floating references的部分,其中详细介绍了一些内容。浮动引用可能看起来有点模糊,但它们对C非常有用,因此花几分钟时间来真正理解它们是一个好主意。

我将假设您了解引用计数的工作原理 - 如果没有大量文档,请花几分钟时间阅读。

首先,让我们看看如果g_variant_new_boolean返回常规引用,您的示例会发生什么。当您第一次获得该值时,引用计数将为1.当您将其传递给g_variant_new时,g_variant_new会将引用计数增加到2.在某些时候,我假设您将处置{{ 1}},此时another_v的引用计数将降为1 ......但请记住,在引用计数达到0之前,内存不会被释放。

为了解决这个问题,您有两种选择。第一个是让a_v窃取来电者的参考,这基本上是一个解决方案。当您致电g_variant_new(或任何类似的功能)时,您会放弃您的参考,因此将来每次您想要将其传递给其他人时,您需要手动引用g_variant_new

另一种选择是在完成后手动取消它。它不是世界末日,但很容易忘记做错或错误(比如忘记在错误路径中取消它)。

GVariant所做的是返回“浮动”参考。最简单的思考方式(恕我直言)是第一次调用它a_v它并没有真正做任何事情 - 它只是“沉没”浮动引用。引用计数从1到1. g_variant_ref的后续调用会增加引用计数。

现在让我们看看你的例子实际发生了什么。 g_variant_ref返回浮动引用。然后,您将其传递给g_variant_new_booleang_variant_new会调用g_variant_ref,这会吸收浮动引用。引用计数现在为1,当another_v的引用计数达到0 a_v时,引用计数将递减,在这种情况下将达到0并且所有内容都将被释放。您无需致电g_variant_unref

关于浮动引用的很酷的部分是这样的事情:

GVariant *a_v = g_variant_new_boolean(TRUE);
GVariant *another_v = g_variant_new("v", a_v);
GVariant *yet_another_v = g_variant_new("v", a_v);

g_variant_new被调用时,第二次a_v的引用计数将再次递增(至2)。在第二次将g_variant_ref传递给a_v之前无需调用g_variant_new - 第一次调用看起来就像第一次调用一样,并且一致性是API中非常好的功能。

此时它可能很明显,但是,您需要在g_variant_unref上调用another_v(在最后一个示例中,yet_another_v)。

答案 1 :(得分:0)

参考计数系统在GObject的手册中有解释,特别是在Object Memory Management部分。

何时使用它可能取决于您的应用程序(变量的所有权如何起作用)。

这个想法类似于i-node在处理文件时在Unix / Linux中的工作方式。文件是一个对象,位于存储中的特定块中。每当您为该文件创建符号链接时,该文件由一个额外文件拥有(引用计数增加)。每当删除符号链接时,引用计数都会减少。当没有任何东西拥有该对象时,它就可以被销毁(或者可以将空间返回给系统)。

如果您销毁某个对象,并且没有任何内容链接该对象,则无法再使用它。如果您的对象可能有多个所有者,那么您可能希望使用引用计数,因此当其中一个所有者删除一个计数器时,该对象不会被销毁...直到最后一个所有者销毁它。