Cross-platform way to find out the approximate amount of RAM

Actually, so far, a little clumsy method has come to mind:

     BYTE GetAvailableMemory(){

        llu MaxMemory = Settings::defaultmemory; // Gb
        std::vector<BYTE> tester;

        while (true){
            try {
                tester.resize(MaxMemory*1073741824);
            } catch (std::bad_alloc& e) {
                tester.clear();
                MaxMemory--;
                return ((MaxMemory) >= Settings::defaultmemory) ? MaxMemory : 0;
            }
            MaxMemory++;
        }
        return 0;
    }

This method works on a system with 16 GB of RAM,
BUT! First - it does not work (xs why) on 32-bit systems, because already on the allocation of 2Gb of the vector, it flies into an error Second , this method runs for about 12 seconds, which is also a long time.
Actually, my question is whether it is possible to somehow optimize this clumsy memory counter and whether it will also work on Linux and mac, as on Windows (not will it put the system down)?

Author: Alrott SlimRG, 2020-08-14

2 answers

For windows, the following method is more correct

#include <Windows.h> 
typedef unsigned long long uint64_t;

uint64_t GetAvailableMemory() {
    typedef BOOL(WINAPI* PGMSE)(LPMEMORYSTATUSEX);

    PGMSE pGMSE = (PGMSE)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx");
    if (pGMSE != 0)
    {
        MEMORYSTATUSEX mi;
        memset(&mi, 0, sizeof(MEMORYSTATUSEX));
        mi.dwLength = sizeof(MEMORYSTATUSEX);
        if (pGMSE(&mi) == TRUE)
            return mi.ullAvailPhys;
        else
            pGMSE = 0;
    }
    if (pGMSE == 0)
    {
        MEMORYSTATUS mi;
        memset(&mi, 0, sizeof(MEMORYSTATUS));
        mi.dwLength = sizeof(MEMORYSTATUS);
        GlobalMemoryStatus(&mi);
        return mi.dwAvailPhys;
    }
    return 0; // или киньте исключение
}

For Linux, you will need to look in the direction of /proc/meminfo Here is an example of reading MemFree

#include <fstream>

unsigned long get_mem_total() {
    std::string token;
    std::ifstream file("/proc/meminfo");
    while (file >> token) {
        if (token == "MemAvailable:") {
            unsigned long mem;
            if (file >> mem) {
                return mem;
            }
            else {
                return 0;
            }
        }
        file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    return 0; // можете кинуть исключение
}

In any case, this will have to be done by preprocessors

 2
Author: AndryS1, 2020-08-16 13:24:31

Option for Linux: use the function sysinfo

// get_info.cxx
#include <sys/sysinfo.h>

#include <iostream>

int main(int argc, const char** argv) {
    struct sysinfo info{};

    if (0 == sysinfo(&info))
    {
        std::cout << "info.freeram  : " << info.freeram << std::endl;
        std::cout << "info.totalram : " << info.totalram << std::endl;
    }
    else
    {
        std::cerr << "call sysinfo fail" << std::endl;
    }
    

    return 0;
}

Build:

g++ get_info.cxx -o get_info

Output on my system (Debian/testing)

$> free
              total        used        free      shared  buff/cache   available
Mem:       16399300     7191280      428588      166348     8779432     8751060
Swap:       8375292        4352     8370940

$> ./build/get_info
info.freeram  : 431308800
info.totalram : 16792883200
 1
Author: Maxim Timakov, 2020-08-16 22:51:19