简体   繁体   English

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

[英]API call to get current heap size of process?

I am debugging a slow memory leak in a large C++ application, I'd like to print out the current heap size at various points in the program. 我在大型C ++应用程序中调试缓慢的内存泄漏,我想在程序的各个点打印出当前的堆大小。

Aside from opening and parsing /proc/PID/statm is there any library API call from which I can get this information? 除了打开和解析/proc/PID/statm是否有任何库API调用,我可以从中获取此信息?

One post suggested sbrk() , however, that returns the current heap pointer – not 100% what I want. 然而,有一篇文章建议sbrk()返回当前的堆指针 - 而不是我想要的100%。 (second question: do changes in the sbrk() value correspond to changes in the current heap size?) (第二个问题: sbrk()值的变化是否与当前堆大小的变化相对应?)

I've looked but it seems strange that there'd be no system call... 我看了,但似乎很奇怪没有系统调用......

Thanks 谢谢

UPDATE I 更新我

I've done some test comparision between calling sbrk() and reading proc/.../statm . 我在调用sbrk()和读取proc/.../statm之间做了一些测试比较。 It appears that sbrk() does not reflect actual allocations . 似乎sbrk() 不反映实际分配 Instead it appears that statm measures actual allocations while sbrk() shows the total heap size. 相反,似乎statm测量实际分配,而sbrk()显示总堆大小。

This total heapsize increments in big chunks (equal to page size?). 这个总大小的增量大块(等于页面大小?)。

The test program below produces this output ( Heap Size as reported by sbrk() and memory usage as reported by /proc/.../statm , clearly showing a difference: 下面的测试程序产生了这个输出(由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

Test Program 测试程序

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

Since glibc's new is based on malloc() , the malloc information and debugging functions can be used; 由于glibc的new基于malloc() ,因此可以使用malloc信息和调试功能; for example you could add a call of malloc_stats() to your application. 例如,您可以向应用程序添加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. malloc_stats ()函数打印(在标准错误上)有关malloc (3)和相关函数分配的内存的统计信息。 ...

You might also have a look at 你可能也看看

  • mallinfo() , mallinfo()

    The mallinfo () function returns a copy of a structure containing information about memory allocations performed by malloc (3) and related functions. mallinfo ()函数返回一个结构的副本,该结构包含有关malloc (3)和相关函数执行的内存分配的信息。 ...

  • malloc_hook , malloc_hook

    The GNU C library lets you modify the behavior of malloc (3) , realloc (3) , and free (3) by specifying appropriate hook functions. GNU C库允许您通过指定适当的钩子函数来修改malloc (3)realloc (3)free (3)的行为。 You can use these hooks to help you debug programs that use dynamic memory allocation, for example. 例如,您可以使用这些挂钩来帮助您调试使用动态内存分配的程序。

  • and mtrace() . mtrace()

    The mtrace () function installs hook functions for the memory-allocation functions ( malloc (3), realloc (3) memalign (3), free (3)). mtrace ()函数为内存分配函数安装钩子函数( 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. 跟踪信息可用于发现内存泄漏并尝试释放程序中的未分配内存。

I am debugging a slow memory leak in a large C++ application 我正在调试大型C ++应用程序中的慢速内存泄漏

You should try using valgrind (after compiling all your code with -g ). 您应该尝试使用valgrind (在使用-g编译所有代码之后)。 It is a very good tool to track memory leaks (but it does slow down your program by a significant factor, perhaps x3 or x10 at least). 它是一个非常好的工具来跟踪内存泄漏(但它确实会使您的程序减慢一个重要因素,至少可能是x3或x10)。

I'd like to print out the current heap size at various points in the program. 我想在程序的各个点打印出当前的堆大小。

I am not sure that heap size has a very well defined meaning (but see other answers to your question). 我不确定堆大小是否具有非常明确的含义(但请参阅您的问题的其他答案)。 The OS provides and manages the virtual address space of your process , and some parts of that are conventionally called "heap". 操作系统提供并管理进程虚拟地址空间 ,其中一些部分通常称为“堆”。 You could use proc(5) and parse (from inside your program) /proc/self/stat , /proc/self/statm , /proc/self/status , /proc/self/maps , and this can be quick. 您可以使用proc(5)解析 (从您的程序内部) /proc/self/stat/proc/self/statm/proc/self/status/proc/self/maps ,这可以很快。 Also use the pmap(1) , ps(1) , top(1) commands (all using /proc/ internally). 还可以使用pmap(1)ps(1)top(1)命令(全部使用/proc/ internal)。 The mmap(2) & munmap , mprotect(2) (and old sbrk(2) ) system call s can change your virtual address space. mmap(2)munmapmprotect(2) (和旧的sbrk(2)系统调用可以改变你的虚拟地址空间。 the C++ new uses malloc which often use mmap . C ++ new使用malloc ,它经常使用mmap However, free or delete often mark a released memory zone as reusable by future malloc -s but don't give up the memory to the system. 但是, freedelete通常将释放的内存区域标记为可由未来的malloc -s重用,但不会将内存放弃到系统中。

PS. PS。 If valgrind is not working, my guess is that you have corrupted your memory, which is even more bad than just a memory leak. 如果valgrind不工作,我的猜测是你已经损坏了你的内存,这比内存泄漏更糟糕。 Consider trying some sanitizer (and other instrumentation ), perhaps the address sanitizer . 考虑尝试一些消毒剂(和其他仪器 ),也许是地址消毒剂 Of course enable all warnings and debug info (so compile with g++ -Wall -Wextra -g ) and take time to improve the source code to get no warnings at all. 当然启用所有警告和调试信息(因此使用 g++ -Wall -Wextra -g编译)并花时间改进源代码以完全不发出警告。 Recent GCC compilers (so GCC 8 in august 2018) gives better warnings and have improved sanitizrs than older ones, so it could be worth to update your g++ compiler. 最近的GCC编译器(因此,2018年8月的GCC 8)提供了更好的警告,并且比旧版本具有更好的清理,因此更新g++编译器可能是值得的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM