内存泄漏检测中应使用哪个vsize,size和rss?

pdp*_*pdp 4 c memory size rss

这三个值,的VSIZE大小RSSps输出是适合于在快速存储器泄漏检测用?就我的目的而言,如果一个进程已经运行了几天并且其内存一直在增加,那么这足以表明它正在泄漏内存。我知道最终应使用像valgrind这样的工具,但是它的使用具有侵入性,因此并不总是可取的。

就我的理解而言,我编写了一段简单的C代码,基本上分配了1 MiB的内存,将其释放,然后再次分配1 MiB。它还会在每步之前休眠10秒钟,这使我有时间查看的输出ps -p <pid> -ovsize=,size=,rss=。这里是:

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>

#define info(args...) printf(args)

char* bytes(char* str, uint32_t size, uint32_t n)
{
    char* unit = "B";

    if (n > 1000) {
        n /= 1000;
        unit = "KB";
    }
    if (n > 1000) {
        n /= 1000;
        unit = "MB";
    }

    snprintf(str, size, "%u %s", n, unit);
    return(str);
}

void* xmalloc(size_t size)
{
    char msg[64];
    size_t max = sizeof(msg);
    void *p = NULL;

    info("Allocating %s\n", bytes(msg, max, size));
    p = malloc(size);
    memset(p, '1', size);
    return(p);
}


void* xfree(void* p, size_t size)
{
    char msg[64];
    size_t max = sizeof(msg);
    info("Freeing %s\n", bytes(msg, max, size));
    free(p);
    return(NULL);
}
void nap()
{
    const int dur = 10;
    info("Sleeping for %d seconds\n", dur);
    sleep(dur);
}

int main(void)
{
    int err = 0;
    size_t kb = 1024;
    size_t block = 1024 * kb;
    char* p = NULL;

    nap();
    p = xmalloc(block);
    nap();
    p = xfree(p, block);
    nap();
    p = xmalloc(block);
    nap();

    return(err);
}
Run Code Online (Sandbox Code Playgroud)

现在,ps它从Shell脚本每两秒钟运行一次,该脚本还帮助打印​​测量时间戳。其输出为:

# time vsize size rss
1429207116   3940   188   312
1429207118   3940   188   312
1429207120   3940   188   312
1429207122   3940   188   312
1429207124   3940   188   312
1429207126   4968  1216  1364
1429207128   4968  1216  1364
1429207130   4968  1216  1364
1429207132   4968  1216  1364
1429207135   4968  1216  1364
1429207137   3940   188   488
1429207139   3940   188   488
1429207141   3940   188   488
1429207143   3940   188   488
1429207145   5096  1344  1276
1429207147   5096  1344  1276
1429207149   5096  1344  1276
1429207151   5096  1344  1276
1429207153   5096  1344  1276
Run Code Online (Sandbox Code Playgroud)

从上面的值开始,并记住手册页中对的描述,在ps(1)我看来,最好的量度是vsize。这种理解正确吗?请注意,手册页指出大小是脏页总数的度量,而rss是物理内存中的页数。这些可能会大大低于该进程使用的总内存。

在运行GNU / Linux 3.2.0-4-amd64的Debian 7.8上尝试了这些实验。

Gre*_*ods 7

一般来说vsize,流程的总虚拟大小()是衡量流程大小的主要指标。 rss只是此刻恰好在使用实际内存的部分。 size衡量实际修改了多少个页面。

不断增加的vsize,相对稳定的或环状的sizerss值可能会建议堆碎片或不良堆分配算法。

持续增加vsizesize相对稳定,rss可能表明内存泄漏,堆碎片或不良的堆分配器算法。

您将必须了解给定程序如何使用内存资源,以便仅使用这些外部资源来衡量进程资源的使用情况,以估计该程序是否遭受内存泄漏。

其中的一部分涉及到对C库malloc()free()例程如何管理堆的一些了解,包括在内部需要多少额外的内存来管理活动分配列表,如何处理堆的碎片以及如何处理将堆中未使用的部分释放回操作系统。

例如,您的测试表明,该进程的总虚拟大小及其所需的“脏”页面的数量,在该程序第二次再次分配相同的内存量时都略有增加。这可能显示的某些开销malloc(),即到那时为止其自身内部数据结构所需的内存量。如果程序做了另一个这本来是有趣的,看看发生了什么事free(),并sleep()退出之前。修改您的代码,使其sleep()在调用malloc()和之间进行调用memset(),然后观察的结果,可能也很有帮助ps

因此,一个简单的程序应该只显示相对稳定的状态vsize,该程序只需要运行固定数量的内存即可运行,或者分配内存来执行特定的工作单元,然后在该工作单元完成后释放所有内存。假设它一次不会处理一个以上的工作单元,并且具有“不良”的分配模式,这会导致堆碎片。

正如您所指出的,像这样的工具valgrind,以及对程序内部实现的深入了解,对于显示实际的内存泄漏并证明它们仅由程序负责是必要的。

(顺便说一句,您可能希望稍微简化代码- info()尤其不要使用不必要的宏,对于这种类型的示例,请尝试以较大的单位打印值,使用额外的变量进行大小计算等。 ,也更多是混淆而不是帮助。太多的printfs也混淆了代码-仅使用您需要的代码来查看程序所处的步骤以及查看编译时未知的值。)