以下 Vala 代码与 C 结合导致内存泄漏,我无法理解它。
Main.vala
using GLib;
[CCode (cname = "c_function")]
public static extern void c_function (out Tree<int, Tree<int, string>> tree);
public static int main () {
Tree<int, Tree<int, string>> tree;
c_function (out tree);
// If code were to end here and return 0, no memory leak happens, but
// if we call c_function again, memory leak happens according to valgrind
c_function (out tree); // Leak happens on this second call
return 0;
}
main.c
#include <glib.h>
gint treeCompareFunction (gint a, gint b);
void extern c_function (GTree **tree) {
*tree = g_tree_new ((GCompareFunc)treeCompareFunction);
for (int i = 0; i < 3; i++) {
// Memory leak in the next line when function is called a second time
GTree * nestedTree = g_tree_new ((GCompareFunc)treeCompareFunction);
g_tree_insert (nestedTree, i, "value 1");
g_tree_insert (*tree, i, (gpointer) nestedTree);
}
}
gint treeCompareFunction (gint a, gint b) {
if (a < b) return -1;
if (a == b) return 0;
return 1;
}
我不明白为什么如果我只调用一次 C 函数就不会发生内存泄漏,但是如果我第二次调用它,main.c 的 line 10> 在 for 循环中创建树会导致内存泄漏。
代码是用
编译的valac Main.vala main.c -g
然后运行
valgrind --leak-check=yes ./Main
我想知道是否可以解决它。在第二次调用 C 函数之前,我尝试在 Vala 代码中清空树。没有成功。如果在第二次调用 C 函数时它不是 NULL,还尝试销毁作为参数传递的树。也没有成功。仍有内存泄漏。
最佳答案
查看您提供的代码,我会考虑使用 g_tree_new_full ()
而不是 C 代码中的 g_tree_new ()
。
您正在重新使用 tree
作为 Vala 代码中的输出参数。所以在第二次调用时,分配给 tree
的第一个值应该被释放。我希望 Vala 生成一个调用来执行此操作,但我没有编写任何示例代码来检查。您可以使用 --ccode
切换到 valac
来编译 Vala 代码以检查生成的 C。
只要 Vala 正在调用 g_tree_unref ()
,那么 C 代码的设置不会释放嵌套树。您需要一个 GDestroyNotify
函数,以便将嵌套树传递给 g_tree_new_full ()
。
更新
错误在您的 C 代码中。你的 C 代码应该是:
#include <glib.h>
gint treeCompareFunction (gint a, gint b);
void extern c_function (GTree **tree) {
*tree = g_tree_new_full ((GCompareFunc)treeCompareFunction,
NULL,
NULL,
g_tree_unref
);
for (int i = 0; i < 3; i++) {
GTree * nestedTree = g_tree_new ((GCompareFunc)treeCompareFunction);
g_tree_insert (nestedTree, i, "value 1");
g_tree_insert (*tree, i, (gpointer) nestedTree);
}
}
gint treeCompareFunction (gint a, gint b) {
if (a < b) return -1;
if (a == b) return 0;
return 1;
}
注意在使用 g_tree_new_full
时使用 g_tree_unref
作为 GDestroyNotify
函数。
Valgrind 泄漏摘要现在报告:
==22035== LEAK SUMMARY:
==22035== definitely lost: 0 bytes in 0 blocks
==22035== indirectly lost: 0 bytes in 0 blocks
==22035== possibly lost: 1,352 bytes in 18 blocks
之前,使用您问题中的代码,泄漏摘要是:
==21436== LEAK SUMMARY:
==21436== definitely lost: 288 bytes in 6 blocks
==21436== indirectly lost: 240 bytes in 6 blocks
==21436== possibly lost: 1,352 bytes in 18 blocks
关于c - 将 Vala 与 C 结合使用时出现内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50403427/