我试图在大型应用程序中找到缓慢的内存泄漏。
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);
}