c++ - 获取进程当前堆大小的 API 调用?

标签 c++ c linux heap-memory

我正在调试大型 C++ 应用程序中的缓慢内存泄漏,我想打印出程序中各个点的当前堆大小。

除了打开和解析 /proc/PID/statm 之外,是否有任何库 API 调用可以从中获取此信息?

一篇文章建议使用 sbrk(),但是它返回当前堆指针——不是我想要的 100%。 (第二个问题:sbrk() 值的变化是否对应于当前堆大小的变化?)

我看过了,但是没有系统调用似乎很奇怪......

谢谢

更新一

我在调用 sbrk() 和读取 proc/.../statm 之间做了一些测试比较。 sbrk() 似乎没有反射(reflect)实际分配情况。相反,statm 似乎测量实际分配,而 sbrk() 显示总堆大小。

这个总堆大小以大块的形式递增(等于页面大小?)。

下面的测试程序产生了这个输出(Heap Sizesbrk() 报告,内存使用情况 报告/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();
}

最佳答案

由于glibc的new是基于malloc()的,所以可以使用malloc信息和调试函数;例如,您可以添加 malloc_stats() 的调用到您的应用程序。

#include <malloc.h>
…
    malloc_stats();

The malloc_stats() function prints (on standard error) statistics about memory allocated by malloc(3) and related functions. …

你也可以看看

  • mallinfo() ,

    The mallinfo() function returns a copy of a structure containing information about memory allocations performed by malloc(3) and related functions. …

  • malloc_hook ,

    The GNU C library lets you modify the behavior of malloc(3), realloc(3), and free(3) by specifying appropriate hook functions. You can use these hooks to help you debug programs that use dynamic memory allocation, for example.

  • mtrace() .

    The mtrace() function installs hook functions for the memory-allocation functions (malloc(3), realloc(3) memalign(3), free(3)). These hook functions record tracing information about memory allocation and deallocation. The tracing information can be used to discover memory leaks and attempts to free nonallocated memory in a program.

关于c++ - 获取进程当前堆大小的 API 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41093780/

相关文章:

c++ - 为什么要把 std::lock 放在 std::lock_guard 之前

c - 代码片段的说明(结构)

c - 将读取行读取的字符打印到标准输入

java - 如何: Java listening for events captured by C thread

linux - MySQL 启动后在启动时运行脚本

c++ - §14/2 中的 "last component"一词的含义是什么?

c++ - 无法从 Object 转换为 Int

linux - 避免在变量内部使用 ls 的更好方法

c++ - 验证 C/C++ 有符号右移是否是特定编译器的算术?

linux - Makefile:make 期间出错