查找内存泄漏的proc / statm的可靠性

时间:2016-12-11 17:30:39

标签: c++ memory-leaks

我试图在大型应用程序中找到缓慢的内存泄漏。

ps显示VSZ缓慢增长,直到应用程序在运行12-18小时后崩溃。不幸的是,valgrind,leakcheak等并没有用(Valgrind因非法指令而失败)。

或者,我一直在打印/proc/statm的内容,大约每隔10秒,我看到statm的第一个字段(总程序大小)增加了20-30个字节。

我已将其追溯到一个功能,但它没有意义。违规函数读取目录并在std :: set上执行clear()。功能中的内容会增加内存占用量?并且......为什么在目录关闭后内存不会减少?

跟踪输出:

DvCfgProfileList::obtainSystemProfileList() PRE MEMORY USAGE: 27260 11440 7317 15 0 12977 0
DvCfgProfileList::obtainSystemProfileList() MID 1 MEMORY USAGE: 27296 11440 7317 15 0 13013 0
DvCfgProfileList::obtainSystemProfileList() MID 2 MEMORY USAGE: 27296 11443 7317 15 0 13013 0
DvCfgProfileList::obtainSystemProfileList POST MEMORY USAGE: 27288 11443 7317 15 0 13005 0

重大问题

我可以依赖读/ proc / statm来立即读取进程内存吗? This Unix/Linux Posting表示“每次访问都会更新”。

如果为true,那么为什么它表明obtainSystemProfileList()正在泄漏?

编辑我

我添加了Unix / Linux帖子的链接。因此,如果读取/proc/.../statm导致直接和立即内核调用,那么内核是否有一些时间延迟更新其自己的内部结果?如果代码片段确实没有内存泄漏,那么还有什么能解释几行代码中mem值的变化?

编辑II

调用getrusage()会提供更直接,更准确的进程内存使用情况吗? (或者只是将内核调用与读取/proc/.../statm相同,可能会延迟吗?

内核是32位3.10.80-1,如果这有任何区别......

代码片段:

bool
DvCfgProfileList::obtainSystemProfileList()
{
    TRACE(("DvCfgProfileList::obtainSystemProfileList() PRE "));
    DvComUtil::printMemoryUsage();

    DIR *pDir = opendir(SYSTEM_PROFILE_DIRECTORY);
    if (pDir == 0)
    {
        mkdir(SYSTEM_PROFILE_DIRECTORY, S_IRWXU | S_IRWXG | S_IRWXO);
        pDir = opendir(SYSTEM_PROFILE_DIRECTORY);
        if (pDir == 0)
        {
            TRACE(("%s does not exist or cannot be created\n", SYSTEM_PROFILE_DIRECTORY));
            return false;
        }
    }

    TRACE(("DvCfgProfileList::obtainSystemProfileList() MID 1 "));
    DvComUtil::printMemoryUsage();

    mpProfileList->clearSystemProfileList(); // calls (std::set) mProfileList.clear()

    TRACE(("DvCfgProfileList::obtainSystemProfileList() MID 2 "));
    DvComUtil::printMemoryUsage();

    struct dirent *pEntry;
    while ((pEntry = readdir(pDir)) != 0)
    {
        if (!strcmp(pEntry->d_name, ".") || !strcmp(pEntry->d_name, ".."))
            continue;

        TRACE(("Profile name = %s\n", pEntry->d_name));
        mpProfileList->addSystemProfile(std::string(pEntry->d_name));
    }
    closedir(pDir);

    printf("DvCfgProfileList::obtainSystemProfileList POST ");
    DvComUtil::printMemoryUsage();

    return true;
}


/* static */ void
DvComUtil::printMemoryUsage()
{
    char fname[256], line[256];
    sprintf(fname, "/proc/%d/statm", getpid());

    FILE *pFile = fopen(fname, "r");
    if (!pFile)
        return;

    fgets(line, 255, pFile);
    fclose(pFile);
    printf("MEMORY USAGE: %s", line);
}

0 个答案:

没有答案