如何找出 Linux 上的 GNU C++ 中剩余的可用内存量

Posted

技术标签:

【中文标题】如何找出 Linux 上的 GNU C++ 中剩余的可用内存量【英文标题】:How do I find out how much free memory is left in GNU C++ on Linux 【发布时间】:2008-12-24 09:40:22 【问题描述】:

我正在编写一个 C++ 程序(使用 gcc 编译并在 RedHat Linux 上运行)。程序需要在运行时知道堆栈上剩余多少空间以及堆中剩余多少。我意识到这个问题(关于堆)可能没有明确的答案,所以或者,我可以使用已经从堆中分配的内存量。是否有库/系统函数调用可以为我提供这些数据?

我想补充一点,我只需要这个来进行调试,并且只需要粗略的估计,所以快速而肮脏的解决方案是完全可以接受的。但是,我需要非常频繁地查询内存使用情况,因此无法接受 Unix 命令行实用程序并解析其输出。

【问题讨论】:

【参考方案1】:

您可能可以创建自己的 new 和 delete 函数来封装真正的 new 和 delete 运算符,同时注意内存使用情况。

对于堆栈,C 中有一个技巧,您可以查看当前函数中定义的第一个局部变量的地址,以粗略了解当前堆栈指针的位置。我想它应该在 C++ 中工作,但还没有尝试过。

【讨论】:

【参考方案2】:

在 linux 上你可以阅读 /proc/pid/status

【讨论】:

【参考方案3】:

请注意,在 32 位系统上,堆栈向下增长,堆向上增长,两者可能会在中间的某个地方相遇。因此,空间可能会分配给堆栈或堆,但不能同时分配给两者。请注意,共享内存段(如果您使用它们)会使内存映射复杂化。动态加载(共享)库也是如此。

+------------+
|    stack   | high addresses
|      |     |
|      v     |
+------------+
|            |
|   unused   |
|            |
+------------+
|            |
|      ^     |
|      |     |
|    heap    |
|            |
+------------+
|            |
|     bss    |
|            |
+------------+
|            |
|    data    |
|            |
+------------+
|            |
|    text    |
|            | low addresses
+------------+

在 64 位系统上,有足够的地址空间可以在发生冲突之前用完实际内存和虚拟内存。

另外,请注意(至少某些版本的)Linux 愿意说可以分配的内存比它们实际支持的更多 - 它们过度使用。那不是很好。这意味着像试用内存分配这样的实际实验可能会给你一种错误的安全感。

最有可能的是,您最好询问“还剩 x MB (GB?) 的空间吗”,而不是“还剩多少 MB (GB?) 的空间”。其他人指出/proc 文件系统是使用多少内存的信息来源。我不确定它是否可靠地告诉您有多少内存可供抓取。

【讨论】:

【参考方案4】:

这是一个 C 函数,用于返回 Raspberry PI 上的可用内存量。 它通过读取 /proc/meminfo 来工作。我不确定它是否适用于其他系统。

#include <stdio.h>
#include <string.h>
// Return the amount of free memory in kbytes.
// Returns -1 if something went wrong.
int getfreememory()

  int returnValue;
  const int BUFFER_SIZE = 1000;
  char buffer[BUFFER_SIZE];
  FILE *fInput;
  int loop;
  int len;
  char ch;
  returnValue = -1;
  fInput = fopen("/proc/meminfo","r");
  if (fInput != NULL)
  
    while (!feof(fInput))
    
      fgets(buffer,BUFFER_SIZE-1,fInput);
      if (feof(fInput))
      
        break;
      
      buffer[BUFFER_SIZE-1] = 0;
      // Look for serial number
      if (strncmp(buffer,"MemFree:",8)==0)
      
        // Extract mem free from the line.
        for(loop=0;loop<BUFFER_SIZE;loop++)
        
          ch = buffer[loop];
          if (ch == ':')
          
             returnValue = 0;
             continue;
          
          if (ch == 0)
          
              break;
          
          if (returnValue >=0)
          
             if (ch >='A')
             
                break;
             
             if ((ch >='0') && (ch <='9'))
             
                returnValue = returnValue * 10 + (ch-'0');
             
          
        
        break;
      
     
    fclose(fInput);
  
  return returnValue;

【讨论】:

【参考方案5】:

您可以在 /proc 命名空间中检查文件 /proc//smaps 和 /proc//maps,其中 是当前进程 ID。

签出this blogpost。

【讨论】:

【参考方案6】:

Valgrind 的 Massif 工具同时支持堆栈和堆 profiling。你可能想检查它的源代码,看看它是怎么做的。

【讨论】:

【参考方案7】:

对于堆部分,您可能遇到了资源限制。查看this。

您可以使用 Valgrind 进行堆栈分析,但您打算用它做什么?栈不像堆。你说,你想这样做是为了调试。如果你的程序运行良好,那么就没有堆栈问题(至少与其大小有关)。

您可以为您创建的线程设置堆栈大小,并通过查看局部变量(不得优化输出)地址来检查堆栈指针值。只需使用初始大小、初始堆栈指针值和当前堆栈指针值进行一些数学运算,您就会得到一些不错的数字。只是不要忘记先找出堆栈方向。这可能会因平台而异。

我认为如果你这么关心堆的使用,那么你的程序可能会泄漏内存。在这种情况下,Valgrind 可以为您指明正确的方向。 Valgrind

【讨论】:

【参考方案8】:

带有 RLIMIT_STACK 参数的 getrlimit 将告诉您总共有多少堆栈空间。 使用 RLIMIT_AS 参数,您可以找出有多少虚拟内存。

更多信息请查看http://linux.die.net/man/2/getrlimit

【讨论】:

以上是关于如何找出 Linux 上的 GNU C++ 中剩余的可用内存量的主要内容,如果未能解决你的问题,请参考以下文章

如何从信号中找出进程的 pid 在 linux 的 c++ 中启动?

GNU g++ 内联汇编块,如 Apple g++/Visual C++?

将 GNU C++ 程序移植到 Visual C++

GNU/Linux 上的 Java 数据库连接

xenomai-GNU/Linux上的RTOS模拟架构实现

linux 学习笔记 GNU工具链简介