API调用以获取当前的过程大小

API call to get current heap size of process?

本文关键字:过程 调用 获取 API      更新时间:2023-10-16

我正在调试大型C 应用程序中的缓慢内存泄漏,我想在程序中的各个点上打印出 current heap大小。/p>

除了打开和解析/proc/PID/statm外,我可以从中获得此信息吗?

但是,一篇帖子建议sbrk()返回当前的堆指针,而不是我想要的100%。(第二个问题:sbrk()值的更改是否对应于当前堆大小的变化?)

我看上去很奇怪,没有系统调用...

谢谢

更新i

我已经在调用sbrk()和读取proc/.../statm之间进行了一些测试比较。看来sbrk() 没有反映实际分配。相反,statm似乎测量了实际分配,而sbrk()显示了总堆大小。

大块的总批量增量(等于页面大小?)。

下面的测试程序会产生此输出( heap size 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: %un", 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 ALLOCATIONn");    
    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();

malloc_stats ()功能prints prints prints(在标准错误)统计信息有关内存的统计信息。 malloc (3)和相关功能。…

您可能还可以看一下

  • mallinfo()

    mallinfo ()函数返回结构的副本,其中包含有关 malloc (3)和相关的内存分配的信息 功能。…

  • malloc_hook

    gnu c库让您可以修改 malloc (3) realloc (3)(3), 和 免费(3)通过指定适当的挂钩功能。您可以使用这些钩子来帮助您调试使用动态内存分配的程序 示例。

  • mtrace()

    mtrace ()函数安装内存分配函数的钩函数( malloc (3), realloc (3)<b(3)> Memalign (3), 免费(3))。这些挂钩功能记录了有关内存分配和交易的信息。跟踪信息可用于发现 内存泄漏并尝试在程序中释放非分配内存。

我正在调试大型C 应用程序中的缓慢内存泄漏

您应该尝试使用valgrind(用-g编译所有代码后)。它是跟踪内存泄漏的一个非常好的工具(但它确实以重要因素减慢了您的程序,也许至少X3或X10)。

我想在程序中的各个点打印出当前的堆尺寸。

我不确定堆大小具有很好的定义含义(但请参阅您的问题的其他答案)。操作系统提供并管理流程的虚拟地址空间,并且某些部分通常称为"堆"。您可以使用PROC(5)和解析(从程序内部)/proc/self/stat/proc/self/statm/proc/self/status/proc/self/maps,这可以很快。还使用PMAP(1),PS(1),顶部(1)命令(全部使用/proc/)。MMAP(2)&amp;munmap,mprotect(2)(和旧的SBRK(2))系统调用可以更改您的虚拟地址空间。C new使用malloc通常使用mmap。但是,freedelete通常将释放的内存区域标记为未来malloc -S可重复使用的内存区域,但不要放弃对系统的内存。

ps。如果valgrind不起作用,我的猜测是您已经破坏了内存,这比内存泄漏更糟糕。考虑尝试一些消毒剂(和其他仪器),也许是地址消毒剂。当然,启用所有警告和调试信息(请使用g++ -Wall -Wextra -g编译),并花时间改进源代码以获取 no 警告。最近的海湾合作委员会编译器(So GCC 8在2018年8月)给出了更好的警告,并且比较旧的编译器改进了Sanitizr,因此更新您的g++编译器可能值得。