c - 将 Vala 与 C 结合使用时出现内存泄漏

标签 c memory-management memory-leaks valgrind vala

以下 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;
}

ma​​in.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 函数就不会发生内存泄漏,但是如果我第二次调用它,ma​​in.cline 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/

相关文章:

c++ - 当前路径/SDL 库

c - 为什么会出现核心转储?

ios - 消息发送到已释放的实例

c - Ptheard 会杀死线程函数中分配的空闲动态内存吗?

c - 尝试将 CSV 数据解析为 C 中的结构时出错

c可以在运行时确定数组的大小吗?

memory-management - current-> mm在Linux内核中为NULL

Delphi 类变量在调用类析构函数之前超出范围

c - 使用动态内存分配和重新散列哈希表在 C 编程中实现哈希表

javascript - 如何控制IE6+jQuery+jQuery-ui内存泄漏?