Как освободить ресурсы, используемые GSettings? - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь написать приложение на C, которое манипулирует GSettings.К сожалению, у меня возникли какие-то утечки памяти, поэтому я попытался их отследить.Я не уверен, что это ошибка библиотеки или я что-то упустил.Это самый маленький пример, который я придумала, который распределяет память до ее сбоя.

#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 I 'используя libglib-2.0 (версия 2.56.3, которая поставляется с Ubuntu 18.04 LTS / Mint).


РЕДАКТИРОВАТЬ 1

В соответствии с запросом в комментариях я публикую вывод valgrind,Я использую команду: valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=50 --show-leak-kinds=definite ./main.Я немного изменил программу, чтобы она была конечной (она повторяется 100.000 раз).Вот вывод для этого измененного параметра.

==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, например:

#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, то он, очевидно, протекает и вылетает.

Вот как вывод valgrind выглядит для этого фрагмента для 100 000 и 1 000 000 итераций.

итераций = 100 000

==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)

iterations = 1.000.000

==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)

Это дает мне некоторое представление о том, что второй код имеет почти одинаковое распределение номеров по сравнению с освобождениями (в обоих случаях diffrence <2000, что, вероятно, является статическим распределением для времени жизнибиблиотека). </p>

Это не так в первом фрагменте, где я использую GSettings объект.Число распределений по сравнению с освобождениями нигде не является постоянным, и оно со временем растет.

Я попытаюсь запустить эту программу с самым последним glib, когда у меня будет доступ к какому-то скользящему выпуску дистрибутива (вероятно, arch), потому что я думаю, что компиляцияпоследний glib и подключить его к Ubuntu слишком сложен для меня.

1 Ответ

0 голосов
/ 25 декабря 2018

Эта «утечка» доступной памяти является артефактом вашей тестовой программы.Каждый раз, когда вы создаете объект GSettings, ему необходимо добавить некоторые правила сопоставления в шину сеанса D-Bus, чтобы он мог получать сигналы от демона dconf.Добавление правила сопоставления означает отправку вызова метода D-Bus демону шины сообщений и затем ожидание ответа.

Создавая 100000 GSettings объектов в строке, вы ставите в очередь 100000 AddMatch вызововк демону шины сообщений, включая 100000 выделений, содержащих информацию об ожидающих ответах на вызовы метода.Однако ваша программа завершает работу до того, как демон шины сообщений отвечает на большинство вызовов AddMatch;поэтому многие из этих распределений, детализирующих ожидающие ответы, по-прежнему распределяются при выходе.

Если ваша программа, например, должна была спать в течение минуты, пока демон шины сообщений не ответил на все вызовы AddMatch, яможно было бы ожидать, что «все еще достижимые» распределения будут соответствовать примеру GFile, который вы запустили.

(Обратите внимание, что можно сделать вызов usleep() в вашей функции main(), чтобы продемонстрировать это, так каквызовы и ответы метода D-Bus обрабатываются в отдельном рабочем потоке.)

...