首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何释放GSettings使用的资源?

如何释放GSettings使用的资源?
EN

Stack Overflow用户
提问于 2018-12-23 18:05:30
回答 1查看 137关注 0票数 1

我正在尝试用C编写应用程序,该应用程序操作GSettings。不幸的是,我遇到了某种类型的内存泄漏,所以我试图找到它们。我不知道这是图书馆的错误还是我遗漏了什么。这是我想出的最小的例子,它分配内存直到崩溃。

代码语言:javascript
复制
#include <glib.h>
#include <gio/gio.h>

int main() {
    while (1) {
        GSettings *settings = g_settings_new("com.linuxmint.updates");

        g_object_unref(settings);
        //g_clear_object(&settings); // This leaks as well but seems to leak "slower"
    }

    return 0;
}

有人能解释一下为什么在这个例子中内存泄漏,以及如何修复它吗?

PS我使用的是libglib-2.0 ( 2.56.3版本,随Ubuntu 18.04 LTS /Mint而来)。

编辑1

根据评论中的要求,我发布了val差制输出。我使用的命令是:valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=50 --show-leak-kinds=definite ./main。我改变了一些程序,使之有限(它循环了100.000次)。以下是更改后的参数的输出。

代码语言:javascript
复制
==16375== Memcheck, a memory error detector
==16375== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16375== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16375== Command: ./main
==16375== 
==16375== 
==16375== HEAP SUMMARY:
==16375==     in use at exit: 297,081,397 bytes in 5,056,358 blocks
==16375==   total heap usage: 26,147,615 allocs, 21,091,257 frees, 1,064,178,170 bytes allocated
==16375== 
==16375== LEAK SUMMARY:
==16375==    definitely lost: 0 bytes in 0 blocks
==16375==    indirectly lost: 0 bytes in 0 blocks
==16375==      possibly lost: 2,840 bytes in 27 blocks
==16375==    still reachable: 297,066,261 bytes in 5,056,238 blocks
==16375==                       of which reachable via heuristic:
==16375==                         length64           : 1,384 bytes in 28 blocks
==16375==                         newarray           : 1,808 bytes in 33 blocks
==16375==         suppressed: 0 bytes in 0 blocks
==16375== Reachable blocks (those to which a pointer was found) are not shown.
==16375== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==16375== 
==16375== For counts of detected and suppressed errors, rerun with: -v
==16375== ERROR SUMMARY: 27 errors from 27 contexts (suppressed: 0 from 0)

我不是专家,但是参数still reachable随着循环数的增加而增长。如果我一直使用一个变量,那么如何实现这些对象(或者更确切地说是结构)?我是不是遗漏了什么?我试着做这里建议的事情:https://developer.gnome.org/gobject/stable/gobject-memory.html

编辑2

我在深入研究这个问题。由于我不确定我的代码是否真的正确,所以我决定将其更改为另一个GObject,如下所示:

代码语言:javascript
复制
#include <glib.h>
#include <gio/gio.h>

int main() {
    while (1) {
        GFile *file = g_file_new_for_path ("/path/to/some/file");

        g_object_unref(file);
        //g_clear_object(&settings);
    }

    return 0;
}

我知道这不会打开任何文件,只会为资源创建句柄,但是随着时间的推移,这段代码的内存使用量是恒定的。如果我删除unref,那么它显然会泄漏和崩溃。

这就是在100.000和1.000.000次迭代中这个片段的val研输出。

迭代= 100.000

代码语言:javascript
复制
==13257== Memcheck, a memory error detector
==13257== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==13257== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==13257== Command: ./main
==13257== 
==13257== 
==13257== HEAP SUMMARY:
==13257==     in use at exit: 159,435 bytes in 1,975 blocks
==13257==   total heap usage: 205,209 allocs, 203,234 frees, 6,758,893 bytes allocated
==13257== 
==13257== LEAK SUMMARY:
==13257==    definitely lost: 0 bytes in 0 blocks
==13257==    indirectly lost: 0 bytes in 0 blocks
==13257==      possibly lost: 2,528 bytes in 26 blocks
==13257==    still reachable: 144,699 bytes in 1,852 blocks
==13257==                       of which reachable via heuristic:
==13257==                         length64           : 1,688 bytes in 32 blocks
==13257==                         newarray           : 1,840 bytes in 35 blocks
==13257==         suppressed: 0 bytes in 0 blocks
==13257== Rerun with --leak-check=full to see details of leaked memory
==13257== 
==13257== For counts of detected and suppressed errors, rerun with: -v
==13257== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

迭代= 1.000.000

代码语言:javascript
复制
==12440== Memcheck, a memory error detector
==12440== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12440== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==12440== Command: ./main
==12440== 
==12440== 
==12440== HEAP SUMMARY:
==12440==     in use at exit: 157,241 bytes in 1,936 blocks
==12440==   total heap usage: 2,005,339 allocs, 2,003,403 frees, 64,363,746 bytes allocated
==12440== 
==12440== LEAK SUMMARY:
==12440==    definitely lost: 0 bytes in 0 blocks
==12440==    indirectly lost: 0 bytes in 0 blocks
==12440==      possibly lost: 2,528 bytes in 26 blocks
==12440==    still reachable: 142,505 bytes in 1,813 blocks
==12440==                       of which reachable via heuristic:
==12440==                         length64           : 1,688 bytes in 32 blocks
==12440==                         newarray           : 1,840 bytes in 35 blocks
==12440==         suppressed: 0 bytes in 0 blocks
==12440== Rerun with --leak-check=full to see details of leaked memory
==12440== 
==12440== For counts of detected and suppressed errors, rerun with: -v
==12440== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

这给了我一些想法,第二段代码的数字分配与空闲几乎相同(在这两种情况下,差异都是< 2000,这可能是库生命周期中的一些静态分配)。

在我使用GSettings对象的第一个片段中,情况并非如此。分配与释放的数量是不固定的,并且随着时间的推移而增加。

当我可以访问一些滚动发行版(可能是arch)时,我将尝试在最新的glib上运行这个程序,因为我认为编译最新的glib并将其插入Ubuntu对我来说太复杂了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-25 00:44:44

这种可达内存的“泄漏”是测试程序的一个工件。每次构造GSettings对象时,它都需要向D总线会话总线添加一些匹配规则,以便它能够接收来自dconf守护进程的信号。添加匹配规则意味着向消息总线守护进程发送一个D总线方法调用,然后等待回复。

通过在一行中创建100000个GSettings对象,您将排队等待对消息总线守护进程的100000次AddMatch调用,其中包括包含有关挂起的方法调用应答的信息的100000次分配。但是,您的程序在消息总线守护进程响应大多数AddMatch调用之前就退出了;因此,许多详细说明挂起的响应的分配仍然在退出时分配。

如果您的程序要在消息总线守护进程响应所有AddMatch调用之前睡上一分钟,我预计“仍然可达”的分配将与您运行的GFile示例一致。

(请注意,在您的usleep()函数中执行main()调用来演示这一点是可以的,因为D总线方法调用和答复是在单独的工作线程中处理的。)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53905960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档