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

15 浏览
0 Comments

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

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

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

有一篇帖子建议sbrk(),但是它返回当前堆指针-不完全是我想要的。 (第二个问题:在sbrk()的值中的更改是否对当前堆大小的更改相应?)

我已经查过了,但奇怪的是没有系统调用...

谢谢

UPDATE

我已经进行了一些测试比较,调用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 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();
}

admin 更改状态以发布 2023年5月21日
0
0 Comments

我正在调试一个大型C++应用中的缓慢内存泄漏问题

你应该尝试使用valgrind(在编译所有代码时使用-g)。它是一个非常好的跟踪内存泄漏的工具(但它会使你的程序显著减慢,可能至少会减慢3到10倍)。

我想在程序的各个点打印出当前的堆大小。

我不确定堆大小有一个明确定义的意义(但请参阅你问题的其他答案)。操作系统提供和管理你的进程的虚拟地址空间,并且其中的一些部分通常被称为“堆”。你可以使用proc(5)并从程序内部解析 /proc/self/stat/proc/self/statm/proc/self/status/proc/self/maps,这可以快速完成。还可以使用pmap(1)ps(1)top(1)命令(内部均使用 /proc/) )。mmap(2)munmapmprotect(2)(以及旧的sbrk(2)系统调用可以改变您的虚拟地址空间。 C++ new使用malloc,后者通常使用mmap。但是,freedelete通常将已释放的内存区域标记为可由未来的malloc重用,但不将内存释放给系统。

PS。 如果valgrind不起作用,我猜想你已经破坏了内存,这比仅仅是内存泄漏更糟糕。 考虑尝试使用一些Sanitizer(和其他仪器),例如地址Sanitizer。 当然,请启用所有警告和调试信息(以使用 g++-Wall-Wextra-g编译),花时间改进源代码以获得零警告。 最新的GCC编译器(因此是2018年8月的GCC 8)提供了更好的警告和改进的Sanitizer,比旧版更值得更新您的g++编译器。

0
0 Comments

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

#include 
…
    malloc_stats();

malloc_stats()函数在标准错误输出中打印有关由malloc(3)和相关函数分配的内存的统计信息。…

您还可以查看以下内容:

  • mallinfo()

    mallinfo()函数返回一个包含有关由malloc(3)和相关函数执行的内存分配信息的结构的副本。…

  • malloc_hook

    GNU C库允许您通过指定适当的钩子函数来修改malloc(3)realloc(3)free(3)的行为。您可以使用这些钩子函数来帮助您调试使用动态内存分配的程序,例如。

  • mtrace()

    mtrace()函数为内存分配函数(malloc(3),realloc(3),memalign(3),free(3))安装钩子函数。这些钩子函数记录与内存分配和释放相关的跟踪信息。跟踪信息可用于发现程序中的内存泄漏和尝试释放未分配内存的情况。

0