如何解决如何正确处理 GLib 中的浮动引用参数?
GLib 中有浮动引用对象。
container = create_container();
container_add_child(container,create_child());
在本例中,create_child
函数创建了不属于任何人的 浮动 对象。 container_add_child
函数获取对象的所有权并成为对象的唯一所有者。当它否认该对象时,该对象被释放。
但是如果 container_add_child
函数没有取得对象的所有权怎么办?在这种情况下,我们会出现内存泄漏。是的,该对象不属于任何人,但它仍然存在于内存中,并且没有人释放该对象的内存。
void handle_object(gpointer object)
{
g_object_ref_sink(object);
// Doing something with object
g_object_unref(object);
}
我们是否必须将 g_object_ref_sink
/ g_object_unref
添加到每个将潜在浮动引用对象作为参数的函数?如果我们删除这些行,那么有人可能会发出这样的调用:handle_object(create_child())
并且我们会得到内存泄漏。该对象将永远“浮动”在内存中。
解决方法
我们是否必须将 g_object_ref_sink
/ g_object_unref
添加到每个将潜在浮动引用对象作为参数的函数?
是的,这就是围绕浮动引用构建 API 很痛苦的原因之一。最好不要使用它们,而是使用显式 ownership transfer annotations((transfer none)
或 (transfer full)
)。
我们是否必须将 g_object_ref_sink / g_object_unref 添加到每个将潜在浮动引用对象作为参数的函数?如果我们删除这些行,那么有人可能会进行这样的调用:handle_object(create_child()) 并且我们将得到内存泄漏。该对象将永远“浮动”在内存中。
智者的问题包含了一半的答案。 将 ref/unref 添加到您使用的任何对象是个好主意。在单线程应用程序或 GUI 方法中可能不是这种情况,您可以 100% 确定甚至没有人有可能销毁对象。但在多线程应用程序中,对象可以随时取消引用,这将导致该对象失效。
但是,在使用 GTK 5 年后,我不清楚需要两个单独的方法(ref_sink
和 ref
):)
试图回答我的问题。
我们是否必须将 g_object_ref_sink / g_object_unref 添加到每个将潜在浮动引用对象作为参数的函数?
我想说,不要将“潜在地” 浮动引用传递给不期望它们的函数。浮动引用是特殊的。您无法访问浮动引用所引用的对象,因为您不拥有它(没有人拥有它)。在使用此类对象之前,您必须调用 g_object_ref_sink
以获取所有权。或者传递对拥有所有权的函数的引用(但是在调用这样的函数之后,您仍然无法使用该对象,因为您仍然不拥有它)。
因此,如果函数假定您拥有该对象,请不要将浮动引用传递给它。在这种情况下,您不必将 g_object_ref_sink
/ g_object_unref
添加到此类函数中。
如果由于某些原因,函数“可能”采用浮动引用,那么,是的,您必须向其添加 g_object_ref_sink
/ g_object_unref
。但是,如果该函数不将引用存储在某处以供以后使用,则该函数可能设计得很糟糕。如果函数仅在本地使用该对象(仅在调用期间),则不要向其添加 g_object_ref_sink
/ g_object_unref
,也不要向其传递浮动引用。如果该函数保存引用以供以后使用,则必须向其中添加 g_object_ref_sink
以获取所有权。但在这种情况下,此函数中将不会有 g_object_unref
调用,因为稍后有人将在函数退出后使用该引用。
所以我想说,将一对 g_object_ref_sink
和 g_object_unref
添加到函数中是不行的。只需添加 g_object_ref_sink
以获得所有权,以便在函数退出后稍后使用引用,就可以了。
是的,这让事情变得困难,因为您必须始终关心引用是否浮动。这就是为什么我个人不喜欢浮动参考的想法。但在向容器添加新对象等情况下,这也使事情变得更容易。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。