reliability of proc/statm for finding memory leak
reliability of proc/statm for finding memory leak
我正在试图找到一个大型应用程序中的慢性内存泄漏。\nps
显示 VSZ
在运行了12-18小时后缓慢增长,最终导致应用程序崩溃。不幸的是,valgrind、leakcheck等工具都没有用(Valgrind出现非法指令错误)。\n另外,我一直在打印 /proc/statm
的内容,每隔大约10秒我会看到 statm
的第一个字段(程序总大小)增加20-30字节。\n我已经追踪到了一个函数,但是它没有意义。这个有问题的函数读取一个目录并在一个 std::set 上执行 clear() 操作。在函数中会导致内存占用增加的是什么?而且...为什么一旦目录关闭后内存不会减少?\n跟踪输出:\n
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
\n重要问题\n我可以依靠读取 /proc/statm 来立即获取进程内存的读数吗?这个 Unix/Linux 帖子表示它在“每次访问时更新”。\n如果是真的,那么为什么它显示 obtainSystemProfileList()
发生了泄漏?\n编辑 I\n我添加了对 Unix/Linux 帖子的链接。所以如果对 /proc/.../statm 的读取导致了直接和即时的内核调用,那么内核更新自己的内部结果是否有一些时间延迟?如果代码片段中确实没有内存泄漏,那么还有什么解释几行代码之间的 mem 值的变化?\n编辑 II\n调用 getrusage()
是否可以提供更即时和准确的进程内存使用情况?(还是只与读取 /proc/.../statm
一样,可能会有延迟的内核调用?)\n内核版本是32位的 3.10.80-1,如果有区别的话...\n代码片段:\n
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(); // 调用 (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); }