reliability of proc/statm for finding memory leak

巧了我就是萌 提交于 2020-01-26 01:44:42

问题


I am trying to find a slow memory leak in a large application.

ps shows the VSZ growing slowly until the application crashes after running for 12-18 hours. Unfortunately, valgrind, leakcheak, etc have not been useful (Valgrind fails with illegal instruction).

Alternatively, I've been printing the contents of /proc/statm over time, and approximately every 10s I see the first field of statm (total program size) increase by 20-30 bytes.

I've tracked it down to one function but it doesn't make sense. The offending function reads a directory and performs a clear() on a std::set. What in the function would increase the memory footprint? And... why doesn't the memory reduce once the directory is closed?

Trace Output:

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

The Big Question

Can I rely on reading /proc/statm for an immediate reading of process memory? This Unix/Linux Posting says it is "updated on every access".

If true, then why does it indicate that obtainSystemProfileList() is leaking?

EDIT I

I added the link to the Unix/Linux post. So if reads of /proc/.../statm result in a direct and immediate kernel call, then is there some time delay in the kernel updating its own internal results? If indeed there is no memory leak in the code fragment, then what else explains the change in mem values across a few lines of code?

EDIT II

Would calling getrusage() provide a more immediate and accurate view of process memory use? (or does it just make the same, potentially delayed, kernel calls as reading /proc/.../statm ?

Kernel is 32-bit 3.10.80-1 if that makes any difference...

Code Fragment:

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);
}

来源:https://stackoverflow.com/questions/41088970/reliability-of-proc-statm-for-finding-memory-leak

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!