Я пытаюсь написать приложение на 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
слишком сложен для меня.