【发布时间】:2017-04-26 21:38:06
【问题描述】:
我正在调试大型 C++ 应用程序中的缓慢内存泄漏,我想在程序的各个点打印出 当前 堆大小。
除了打开和解析 /proc/PID/statm 之外,是否有任何库 API 调用可以从中获取这些信息?
一个帖子建议sbrk(),但是,它返回当前堆指针——不是我想要的 100%。 (第二个问题:sbrk()值的变化是否对应当前堆大小的变化?)
我看过,但是没有系统调用似乎很奇怪......
谢谢
更新我
我在调用sbrk() 和读取proc/.../statm 之间做了一些测试比较。 sbrk() 似乎没有反映实际分配。相反,statm 似乎测量实际分配,而sbrk() 显示总堆大小。
这个总堆大小以大块递增(等于页面大小?)。
下面的测试程序产生了这个输出(sbrk() 报告的堆大小和/proc/.../statm 报告的内存使用情况,清楚地显示了差异:
0 ALLOC: HEAP SIZE: 0
MEMORY USAGE: 1308 201 174 2 0 566 0
1 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 1565 212 184 2 0 823 0
2 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 1822 216 187 2 0 1080 0
3 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 2079 217 187 2 0 1337 0
4 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 2336 218 187 2 0 1594 0
5 ALLOC: HEAP SIZE: 135168
MEMORY USAGE: 2593 219 187 2 0 1851 0
0 FREE: HEAP SIZE: 135168
MEMORY USAGE: 3364 225 189 2 0 2622 0
1 FREE: HEAP SIZE: 135168
MEMORY USAGE: 3107 224 189 2 0 2365 0
2 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2850 223 189 2 0 2108 0
3 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2593 222 189 2 0 1851 0
4 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2336 221 189 2 0 1594 0
5 FREE: HEAP SIZE: 135168
MEMORY USAGE: 2079 220 189 2 0 1337 0
测试程序
class CfgProfileList
{
public:
bool obtainSystemProfileList();
void leakObjTest();
std::set<std::string> mProfileList;
private:
char dummy[1024 * 1024]; // use up some space
};
class ComUtil
{
public:
static void printMemoryUsage();
private:
static unsigned int mHeapOrigin;
};
/* static */
unsigned int ComUtil::mHeapOrigin = 0;
// Print current process memory utilization
/* static */ void
ComUtil::printMemoryUsage()
{
unsigned int pHeap = (unsigned int)sbrk(0);
if (mHeapOrigin == 0)
mHeapOrigin = pHeap;
printf("HEAP SIZE: %u\n", pHeap - mHeapOrigin);
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);
}
void
CfgProfileList::leakObjTest()
{
CfgProfileList *pointerList[50];
int n = 10;
int sleep = 100000;
printf("OBJECT ALLOCATION\n");
for (int i = 0; i < n; i++)
{
pointerList[i] = new CfgProfileList;
printf("%d ALLOC: ", i);
ComUtil::printMemoryUsage();
usleep(sleep);
}
printf("\n");
for (int i = 0; i < n; i++)
{
delete pointerList[i];
printf("%d FREE: ", i);
ComUtil::printMemoryUsage();
usleep(sleep);
}
}
int
main(int argc, char **argv)
{
CfgProfileList pl;
pl.leakObjTest();
}
【问题讨论】:
-
你考虑过使用 valgrind 或类似的吗?
-
不幸的是,Valgrind 不起作用;检测到非法指令字节而死。我已经直接询问了 valgrind 开发人员列表,并且根据他们的建议,我已经 a) 从源代码重建 valgrind,b) 将 gcc 重新编译到目标机器的本机处理器。不工作。可以在这里查看相关问题:stackoverflow.com/questions/41088970/…
-
你的问题是什么?你有非法指令?也许函数指针无效?请添加什么 valgrind 打印。好像是 XY 问题
-
您可以使用自定义分配器(如果您不担心速度,您可能需要编写一个简单的分配器)来检查内存泄漏。有些地方你也可以使用placement new 操作符(从已经分配的内存中分配内存)
-
Stargateur,您可以在此处查看 valgrind 列表中的完整主题:sourceforge.net/p/valgrind/mailman/valgrind-users/thread/…我已经为这个项目放弃了 valgrind。我在 gperftools 上取得了一些成功!
标签: c++ c linux heap-memory