提问人:theCakeCoder 提问时间:3/25/2010 最后编辑:theCakeCoder 更新时间:1/19/2022 访问量:122820
如何获取可用内存 C++/g++?
How to get available memory C++/g++?
问:
我想根据可用内存分配缓冲区。这样,当我进行处理时,内存使用率会上升,但仍保持在可用内存限制中。有没有办法获得可用内存(我不知道虚拟或物理内存状态会有什么不同吗?方法必须与平台无关,因为它将在 Windows、OS X、Linux 和 AIX 上使用。(如果可能的话,我还想为我的应用程序分配一些可用内存,在执行过程中不会改变)。
编辑:我用可配置的内存分配做到了。 我知道这不是一个好主意,因为大多数操作系统都为我们管理内存,但我的应用程序是一个 ETL 框架(打算在服务器上使用,但也在桌面上用作 Adobe indesign 的插件)。所以,我遇到了问题,因为 Windows 不会使用 swap,而是返回错误的 alloc 并且其他应用程序开始失败。正如我被教导要避免撞车一样,我只是想优雅地降级。
答:
没有独立于平台的方法可以做到这一点,不同的操作系统使用不同的内存管理策略。
这些其他堆栈溢出问题将有所帮助:
不过,您应该注意:众所周知,在 linux 中很难获得可用内存的“真实”值。操作系统显示的进程使用的内容并不能保证实际为进程分配的内容。
这是开发嵌入式 Linux 系统(如路由器)时的常见问题,您希望在硬件允许的范围内进行尽可能多的缓冲。下面是一个示例的链接,该示例显示了如何在 linux(在 C 语言中)获取此信息:
评论
在类 UNIX 操作系统上,有 sysconf。
#include <unistd.h>
unsigned long long getTotalSystemMemory()
{
long pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGE_SIZE);
return pages * page_size;
}
在 Windows 上,有 GlobalMemoryStatusEx
:
#include <windows.h>
unsigned long long getTotalSystemMemory()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
return status.ullTotalPhys;
}
所以只要做一些花哨的事情,你就可以开始了。#ifdef
评论
status.ullTotalPhys
unsigned long long
-729088
21474107392
long
size_t
_SC_PHYS_PAGES
使用 sysctl 的 Mac OS X 示例():man 3 sysctl
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/sysctl.h>
int main(void)
{
int mib[2] = { CTL_HW, HW_MEMSIZE };
u_int namelen = sizeof(mib) / sizeof(mib[0]);
uint64_t size;
size_t len = sizeof(size);
if (sysctl(mib, namelen, &size, &len, NULL, 0) < 0)
{
perror("sysctl");
}
else
{
printf("HW.HW_MEMSIZE = %llu bytes\n", size);
}
return 0;
}
(也可以在其他类似 BSD 的操作系统上运行?
评论
对此的“官方”功能是 .但是,您可能想测试您的平台是否具有良好的实施能力。我知道并非所有平台都按预期运行。std::get_temporary_buffer()
评论
您是否考虑过让用户配置用于缓冲区的内存量,以及假设一些保守的默认值,而不是试图猜测?这样一来,你仍然可以在不覆盖的情况下运行(可能稍微慢一点),但如果用户知道应用有 X 内存可用,他们可以通过配置该内存量来提高性能。
我们有理由希望在科学软件的 HPC 中执行此操作。(不包括游戏、网络、商业或嵌入式软件)。科学软件通常会通过数TB的数据来完成一次计算(或运行)(并运行数小时或数周) - 所有这些都不能存储在内存中(如果有一天你告诉我,任何PC,平板电脑或手机的标准TB都是标准,那么科学软件将需要处理PB或更多)。内存量也可以决定有意义的方法/算法的类型。用户并不总是想决定内存和方法 - 他/她还有其他事情要担心。因此,程序员应该对可用的内容(4Gb、8Gb 或 64Gb 左右)有一个很好的了解,以决定一种方法是自动工作还是选择更费力的方法。使用磁盘,但最好使用内存。并且不鼓励此类软件的用户在运行此类软件时在他们的计算机上做太多事情 - 事实上,他们经常使用专用的机器/服务器。
评论
min(physi, 2GiB)
通读了这些答案后,我惊讶地发现有这么多人认为OP的计算机内存属于其他人。这是他的电脑和他的内存,可以按照他认为合适的方式使用,即使它破坏了其他系统。这是一个有趣的问题。在一个更原始的系统上,我会告诉我这一点。为什么 OP 不应该在不打扰其他系统的情况下占用他想要的内存?memavail()
这是一个解决方案,它分配的内存不到可用内存的一半,只是为了友善起见。输出为:
必需的 FFFFFFFF
必需的 7FFFFFFF
必需的 3FFFFFFF
分配的内存大小 = 1FFFFFFF
#include <stdio.h>
#include <stdlib.h>
#define MINREQ 0xFFF // arbitrary minimum
int main(void)
{
unsigned int required = (unsigned int)-1; // adapt to native uint
char *mem = NULL;
while (mem == NULL) {
printf ("Required %X\n", required);
mem = malloc (required);
if ((required >>= 1) < MINREQ) {
if (mem) free (mem);
printf ("Cannot allocate enough memory\n");
return (1);
}
}
free (mem);
mem = malloc (required);
if (mem == NULL) {
printf ("Cannot enough allocate memory\n");
return (1);
}
printf ("Memory size allocated = %X\n", required);
free (mem);
return 0;
}
评论
free
execve
system
malloc()
sysctl()
sysctl
memavail
GlobalMemoryStatusEx
下面的代码给出了以兆字节为单位的总内存和可用内存。适用于 FreeBSD,但您应该能够在您的平台上使用相同/相似的 sysctl 可调参数并执行相同的操作(Linux 和 OS X 至少有 sysctl)
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
int main(){
int rc;
u_int page_size;
struct vmtotal vmt;
size_t vmt_size, uint_size;
vmt_size = sizeof(vmt);
uint_size = sizeof(page_size);
rc = sysctlbyname("vm.vmtotal", &vmt, &vmt_size, NULL, 0);
if (rc < 0){
perror("sysctlbyname");
return 1;
}
rc = sysctlbyname("vm.stats.vm.v_page_size", &page_size, &uint_size, NULL, 0);
if (rc < 0){
perror("sysctlbyname");
return 1;
}
printf("Free memory : %ld\n", vmt.t_free * (u_int64_t)page_size);
printf("Available memory : %ld\n", vmt.t_avm * (u_int64_t)page_size);
return 0;
}
下面是程序的输出, 与我的系统上的 vmstat(8) 输出的比较。
~/code/memstats % cc memstats.c
~/code/memstats % ./a.out
Free memory : 5481914368
Available memory : 8473378816
~/code/memstats % vmstat
procs memory page disks faults cpu
r b w avm fre flt re pi po fr sr ad0 ad1 in sy cs us sy id
0 0 0 8093M 5228M 287 0 1 0 304 133 0 0 112 9597 1652 2 1 97
评论
Linux 当前可用内存:sysconf(_SC_AVPHYS_PAGES
) 和 get_avphys_pages()
总RAM覆盖在 https://stackoverflow.com/a/2513561/895245。sysconf(_SC_PHYS_PAGES);
两者都是 POSIX 的 glibc 扩展,它们提供了当前可用的 RAM 页面总数。sysconf(_SC_AVPHYS_PAGES)
get_avphys_pages()
然后,您只需将它们乘以即可获得当前的可用 RAM。sysconf(_SC_PAGE_SIZE)
最小可运行示例: C - 检查可用的可用 RAM?
以下是在 Linux 平台上获取可用内存的建议:
/// Provides the available RAM memory in kibibytes (1 KiB = 1024 B) on Linux platform (Available memory in /proc/meminfo)
/// For more info about /proc/meminfo : https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-meminfo
long long getAvailableMemory()
{
long long memAvailable = -1;
std::ifstream meminfo("/proc/meminfo");
std::string line;
while (std::getline(meminfo, line))
{
if (line.find("MemAvailable:") != std::string::npos)
{
const std::size_t firstWhiteSpacePos = line.find_first_of(' ');
const std::size_t firstNonWhiteSpaceChar = line.find_first_not_of(' ', firstWhiteSpacePos);
const std::size_t nextWhiteSpace = line.find_first_of(' ', firstNonWhiteSpaceChar);
const std::size_t numChars = nextWhiteSpace - firstNonWhiteSpaceChar;
const std::string memAvailableStr = line.substr(firstNonWhiteSpaceChar, numChars);
memAvailable = std::stoll(memAvailableStr);
break;
}
}
return memAvailable;
}
评论
new
bad_alloc