【问题标题】:Is reusing a variable but memory not being released by the process considered a memory leak?重用变量但进程未释放内存是否被视为内存泄漏?
【发布时间】:2018-05-26 14:50:40
【问题描述】:

在 Vala 中,我有一个来自 Gee 库的 TreeMultiMap,它被创建为类的私有变量。当我使用树多映射并用数据填充它时,进程的内存消耗增加到 14.2 MiB。当我清除仍然是同一个变量的树多重映射并再次使用它,但添加较少的数据时,进程的内存消耗不会增加,但也不会减少。它保持在 14.2 MiB。

代码如下MultiMapTest.vala

using Gee;

private TreeMultiMap <string, TreeMultiMap<string, string> > rootTree;

public static int main () {
    // Initialize rootTree
    rootTree = new TreeMultiMap<string, TreeMultiMap<string, string> > (null, null);

    // Add data repeatedly to the tree to make the process consume memory
    for (int i = 0; i < 10000; i++) {
        TreeMultiMap<string, string> nestedTree = new TreeMultiMap<string, string> (null, null);
        nestedTree.@set ("Lorem ipsum", "Lorem ipsum");
        rootTree.@set ("Lorem ipsum", nestedTree);
    }

    stdout.printf ("Press ENTER to clear the tree...");
    // Wait for the user to press enter
    var input = stdin.read_line ();

    // Clear the tree
    rootTree.clear ();

    stdout.printf ("Press ENTER to continue and refill the tree with less data...");
    // Wait for the user to press enter
    input = stdin.read_line ();

    // Refill the tree but with much less data
    for (int i = 0; i < 10; i++) {
        TreeMultiMap<string, string> nestedTree = new TreeMultiMap<string, string> (null, null);
        nestedTree.@set ("Lorem ipsum", "Lorem ipsum");
        rootTree.@set ("Lorem ipsum", nestedTree);
    }

    stdout.printf ("Press ENTER to quit...");
    // Wait for the user to press enter
    input = stdin.read_line ();
    return 0;
}

valac --pkg gee-0.8 -g MultiMapTest.vala编译

这是否被视为内存泄漏?如果是这样,是否有任何方法可以正确处理这种情况,例如一旦清除树多映射,即使涉及使用其他数据结构,内存也会释放给操作系统?

我使用了 valgrind,但无法检测到任何内存泄漏。我的看法是,一旦为TreeMultiMap 变量分配了内存,除非变量超出范围,否则程序将保持分配的内存直到其生命周期结束,而不是将其释放回操作系统。即使 TreeMultiMap 被清空。

【问题讨论】:

    标签: memory-management vala


    【解决方案1】:

    这与 Vala 关系不大,更多的是与 UNIX 程序处理内存的方式有关。

    当程序启动时,UNIX 内核为程序本身、堆栈和一个称为堆的区域分配内存,该区域可以由程序动态分配内存。从 UNIX 内核的角度来看,堆是一大块内存,程序可以使用 sbrk 请求更多。

    在 C 和大多数其他语言中,您经常需要小块内存。因此,C 标准库有一个代码通过mallocfree 进行内存分配。当您使用malloc 分配内存时,它会将其从堆中的可用空间中取出。当你free它时,它可以被以后的malloc重用。如果没有足够的内存,malloc 将调用sbrk 为程序获取更多内存。不管你有多少空闲,C 标准库在程序结束之前不会将内存还给内核。

    Valgrind 和 Vala 正在讨论内存泄漏问题,您在 malloc 没有 free 的情况下。 pstop 查看sbrk 分配的总内存。

    这意味着如果您malloc 一大块内存,然后free 它,Valgrind 将显示它已正确释放并且它可供您的程序重用,但内核仍然认为它正在被程序使用.

    【讨论】:

    • 优秀的答案。它完美地解释了这种行为。谢谢。虽然我还有一个问题。在使用 gcc 编译的 C 程序中,在同一台 linux 机器上,我使用 calloc() 将 10 MB 内存分配给变量,然后使用 free() 释放它以尝试调查 Vala 的行为方式不同的原因。释放的内存在 C 程序中返回给操作系统。为什么?答案复杂吗?我应该把代码并排问一个新问题吗?
    • Vala 使用 glib 的 slice allocator,它是 C 分配器的包装器。这可以对 Valgrind 隐藏正在发生的事情,因此您可以设置环境变量 G_SLICE=always-malloc 以查看正在发生的事情。
    猜你喜欢
    • 2011-12-14
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 2011-08-21
    • 2011-01-27
    • 2020-07-22
    相关资源
    最近更新 更多