如何获得可用的内存C++/g ++?

the*_*der 61 c++ memory-management cross-platform

我想根据可用的内存分配我的缓冲区.这样,当我进行处理和内存使用量增加时,仍然保持可用的内存限制.有没有办法获得可用的内存(我不知道虚拟或物理内存状态会有什么不同?).方法必须是平台独立的,因为它将用于Windows,OS X,Linux和AIX.(如果可能的话,我还想为我的应用程序分配一些可用的内存,在执行期间它没有改变的人).

编辑:我用可配置的内存分配做到了.我理解这不是一个好主意,因为大多数操作系统为我们管理内存,但我的应用程序是一个ETL框架(打算在服务器上使用,但也在桌面上用作Adobe indesign的插件).因此,我正在运行以发布因为而不是使用交换,Windows将返回错误的alloc,其他应用程序开始失败.当我被教导避免崩溃等等时,只是试图优雅地降级.

Tra*_*kel 141

在类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;
}
Run Code Online (Sandbox Code Playgroud)

在Windows上,有GlobalMemoryStatusEx:

#include <windows.h>

unsigned long long getTotalSystemMemory()
{
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatusEx(&status);
    return status.ullTotalPhys;
}
Run Code Online (Sandbox Code Playgroud)

所以,只要做一些花哨#ifdef的事情,你就会好起来.

  • 它不是我想要耗尽所有的内存,它我不想去加载太多的数据,我无法处理可用的内存(我想留在未使用或一些空间,可能不会被其他进程访问).再一次,我不想愚蠢地想要分配所有可用的内存但是想要决定应该对应用程序设置什么限制因此它不会吸收所有内存并且崩溃~__ (10认同)
  • 这对于我所拥有的与切向相关的任务非常有用:当用户使用大部分物理内存时警告用户.我知道我可以使用更多并管理虚拟内存,但是如果我使用的物理RAM数量超过了我希望能够警告用户的数量,因为这会导致速度变慢,因为会产生分页发生. (3认同)
  • 轻微的挑剔:`status.ullTotalPhys`是一个`unsigned long long`; 如果方法的返回类型很长,那么在某些系统上你会得到无意义的结果.按原样运行代码会导致系统返回值为"-729088",但更改它以匹配ullTotalPhys的类型会产生正确的"21474107392". (3认同)
  • 值得注意的是,`_SC_PHYS_PAGES` 不是 POSIX 规范的一部分。 (3认同)
  • 这是一个很好的观点...我在代码中将 `long` 更改为 `size_t`,这在任何具有非分段寻址的系统上都应该没问题。 (2认同)

小智 29

有理由想在HPC中为科学软件做这件事.(不是游戏,网络,商业或嵌入式软件).科学软件通常会经历数TB的数据来完成一次计算(或运行)(并运行数小时或数周) - 所有这些都无法存储在内存中(如果有一天你告诉我一个太字节是任何PC的标准配置或平板电脑或手机将是科学软件预计将处理数PB或更多的情况).内存量也可以决定有意义的方法/算法类型.用户并不总是想要决定记忆和方法 - 他/她还有其他需要担心的事情.因此,程序员应该很好地了解可用的内容(4Gb或8Gb或64Gb或者这些天),以确定方法是自动工作还是选择更费力的方法.使用磁盘但最好使用内存.并且不鼓励这类软件的用户在运行这样的软件时在他们的计算机上做太多事情 - 事实上,他们经常使用专用的机器/服务器.

  • 至少有理由使用渲染软件来做到这一点。您想使用尽可能多的内存。例如:可用的物理内存(×α,0.5&lt;α&lt;0.8)将是光子贴图大小的限制。+ 一些 `min(physi, 2GiB)` 以避免具有 256GB RAM 的机器需要永远构建光子贴图。但还是。您还可以想象在游戏中漫游,我已经看到引擎通过流输入和输出资产来维护内存目标。内存越多,看得越远。 (2认同)

Wea*_*ane 15

阅读完这些答案后,我惊讶于很多人认为OP的计算机内存属于其他人.他认为合适的是他的计算机和他的记忆,即使它打破了其他系统的要求.这是一个有趣的问题.在一个更原始的系统上我memavail()会告诉我这个.为什么OP不会在不扰乱其他系统的情况下占用尽可能多的内存?

这是一个分配不到一半可用内存的解决方案,只是为了善待.产出是:

必需的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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常糟糕的*解决方案.想象一下,你正在使用计算机,突然它开始交换并慢下来爬行,一些应用程序由于内存不足而失败,网络连接失败等等.你恐慌的是你有恶意软件,关机或运行防病毒软件,并且发现这是由于某些愚蠢的应用程序只是不断地分配和释放它甚至不需要的大量内存. (19认同)
  • 在Linux上你可以使用binutils`ree`命令(或者它是一个bash命令?也许)你可以使用`execve`或`system`启动.一种有趣的方法也可以尝试分配(并写入1),直到无法检测到可用的内存.更不用说检查速度,以便检测到交换. (2认同)
  • 尝试`malloc()`并确定可用内存是一个解决问题的可怕方法; 远非最佳和可用....什么阻止你使用`sysctl()`系列函数并从OS可调参数中获取一些读数?此外,_free memory_的概念从操作系统变为操作系统,例如,FreeBSD和AFAIK OS X也将未使用的内存视为浪费,并将内存用于某些_useful stuff_(对此的回答超出范围)这个主题).看看这个https://www.freebsd.org/cgi/man.cgi?query=sysctl&sektion=3 (2认同)

mik*_*ong 12

没有独立于平台的方法,不同的操作系统使用不同的内存管理策略.

这些其他堆栈溢出问题将有助于:

你应该注意:在Linux中获得可用内存的"真实"值是非常困难的.操作系统显示的进程使用的内容并不能保证实际为进程分配的内容.

在开发嵌入式Linux系统(如路由器)时,这是一个常见的问题,您希望在其中尽可能多地缓冲硬件.这是一个示例的链接,显示如何在linux中获取此信息(在C中):


Pau*_*l R 5

使用sysctl(man 3 sysctl)的Mac OS X示例:

#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;
}
Run Code Online (Sandbox Code Playgroud)

(也可以在其他类似BSD的操作系统上工作?)

  • 这将返回系统中的总物理内存,而不是可用(空闲)内存. (4认同)

fni*_*isi 5

下面的代码给出了以兆字节为单位的总内存和可用内存。适用于 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;
}
Run Code Online (Sandbox Code Playgroud)

下面是程序的输出,与我系统上的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
Run Code Online (Sandbox Code Playgroud)