I just wrote the following C++ function to programatically determine how much RAM a system has installed. It works, but it seems to me that there should be a simpler way to do this. Can someone tell me if I'm missing something?

getRAM()
{
    FILE* stream = popen( "head -n1 /proc/meminfo", "r" );
    std::ostringstream output;
    int bufsize = 128;

    while( !feof( stream ) && !ferror( stream ))
    {
        char buf[bufsize];
        int bytesRead = fread( buf, 1, bufsize, stream );
        output.write( buf, bytesRead );
    }
    std::string result = output.str();

    std::string label, ram;
    std::istringstream iss(result);
    iss >> label;
    iss >> ram;

    return ram;
}

First, I'm using popen("head -n1 /proc/meminfo") to get the first line of the meminfo file from the system. The output of that command looks like

MemTotal: 775280 kB

Once I've got that output in an istringstream, it's simple to tokenize it to get at the information I want. My question is, is there a simpler way to read in the output of this command? Is there a standard C++ library call to read in the amount of system RAM?

share|edit|flag
up vote 55 down vote accepted

On Linux, you can use the function sysinfo which sets values in the following struct:

   #include <sys/sysinfo.h>

   int sysinfo(struct sysinfo *info);

   struct sysinfo {
       long uptime;             /* Seconds since boot */
       unsigned long loads[3];  /* 1, 5, and 15 minute load averages */
       unsigned long totalram;  /* Total usable main memory size */
       unsigned long freeram;   /* Available memory size */
       unsigned long sharedram; /* Amount of shared memory */
       unsigned long bufferram; /* Memory used by buffers */
       unsigned long totalswap; /* Total swap space size */
       unsigned long freeswap;  /* swap space still available */
       unsigned short procs;    /* Number of current processes */
       unsigned long totalhigh; /* Total high memory size */
       unsigned long freehigh;  /* Available high memory size */
       unsigned int mem_unit;   /* Memory unit size in bytes */
       char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */
   };

If you want to do it solely using functions of C++ (i would stick to sysinfo), i recommend taking a C++ approach using std::ifstream and std::string:

unsigned long get_mem_total() {
    std::string token;
    std::ifstream file("/proc/meminfo");
    while(file >> token) {
        if(token == "MemTotal:") {
            unsigned long mem;
            if(file >> mem) {
                return mem;
            } else {
                return 0;       
            }
        }
        // ignore rest of the line
        file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    return 0; // nothing found
}
share|edit|flag
   upvote
  flag
sysinfo works perfectly. Thank you. – Bill the Lizard Dec 8 '08 at 16:52
   upvote
  flag
you may want to close the file handle after reading – segfault Oct 3 '12 at 14:35
1 upvote
  flag
Surely the destructors do that already. – Camille Goudeseune Jul 16 '15 at 16:39
2 upvote
  flag
It is worth noting that freeram in sysinfo is not what most people would call "free RAM". freeram excludes memory used by cached filesystem metadata ("buffers") and contents ("cache"). Both of these can be a significant portion of RAM but are freed by the OS when programs need that memory. sysinfo does contain size used by buffers (sysinfo.bufferram), but not cache. The best option is to use the MemAvailable (as opposed to MemFree) entry in /proc/meminfo instead. – Vicky Chijwani Jul 29 '16 at 11:01
1 upvote
  flag
This Linux kernel commit message explains there are more nuances. It says: "Many programs check /proc/meminfo to estimate how much free memory is available. They generally do this by adding up "free" and "cached", which was fine ten years ago, but is pretty much guaranteed to be wrong today." – Vicky Chijwani Jul 29 '16 at 11:08

Even top (from procps) parses /proc/meminfo, see here.

share|edit|flag

There's no need to use popen(), you can just read the file yourself. Also, if there first line isn't what you're looking for, you'll fail, since head -n1 only reads the first line and then exits. I'm not sure why you're mixing C and C++ I/O like that; it's perfectly OK, but you should probably opt to go all C or all C++. I'd probably do it something like this:

int GetRamInKB(void)
{
    FILE *meminfo = fopen("/proc/meminfo", "r");
    if(meminfo == NULL)
        ... // handle error

    char line[256];
    while(fgets(line, sizeof(line), meminfo))
    {
        int ram;
        if(sscanf(line, "MemTotal: %d kB", &ram) == 1)
        {
            fclose(meminfo);
            return ram;
        }
    }

    // If we got here, then we couldn't find the proper line in the meminfo file:
    // do something appropriate like return an error code, throw an exception, etc.
    fclose(meminfo);
    return -1;
}
share|edit|flag
   upvote
  flag
The first line had of /proc/meminfo was the information I was after. I'm returning to C++ after many years, so I don't yet have a good sense of C vs. C++ style, but I'm working on it. Thanks. :) – Bill the Lizard Dec 8 '08 at 16:27

Remember /proc/meminfo is just a file. Open the file, read the first line, close the file. Voilá!

share|edit|flag

Your Answer

  • Images are exactly like links, but they have an exclamation point in front of them:

    ![a busy cat](https://cdn.sstatic.net/Sites/stackoverflow/img/error-lolcat-problemz.jpg)
    ![two muppets][1]
    
     [1]: http://i.imgur.com/I5DFV.jpg "tooltip"
    

    The word in square brackets is the alt text, which gets displayed if the browser can't show the image. Be sure to include meaningful alt text for screen-reading software.

    Be sure to use text styling sparingly; only where it helps readability.

    *This is italicized*, and so
    is _this_.
    
    **This is bold**, just like __this__.
    
    You can ***combine*** them
    if you ___really have to___.
    

    To break your text into sections, you can use headers:

    A Large Header
    ==============
    
    Smaller Subheader
    -----------------
    

    Use hash marks if you need several levels of headers:

    # Header 1 #
    ## Header 2 ##
    ### Header 3 ###
    

    Both bulleted and numbered lists are possible:

    - Use a minus sign for a bullet
    + Or plus sign
    * Or an asterisk
    
    1. Numbered lists are easy
    2. Markdown keeps track of
     the numbers for you
    7. So this will be item 3.
    
    1. Lists in a list item:
        - Indented four spaces.
            * indented eight spaces.
        - Four spaces again.
    2.  You can have multiple
        paragraphs in a list items.
     
        Just be sure to indent.
    
    > Create a blockquote by
    > prepending “>” to each line.
    >
    > Other formatting also works here, e.g.
    >
    > 1. Lists or
    > 2. Headings:
    >
    > ## Quoted Heading ##
    

    You can even put blockquotes in blockquotes:

    > A standard blockquote is indented
    > > A nested blockquote is indented more
    > > > > You can nest to any depth.
    

    To create code blocks or other preformatted text, indent by four spaces:

        This will be displayed in a monospaced font. The first four spaces
        will be stripped off, but all other whitespace will be preserved.
        
        Markdown and HTML are turned off in code blocks:
        <i>This is not italic</i>, and [this is not a link](http://example.com)
    

    To create not a block, but an inline code span, use backticks:

    The `$` character is just a shortcut for `window.jQuery`.
    

    If you want to have a preformatted block within a list, indent by eight spaces:

    1. This is normal text.
    2. So is this, but now follows a code block:
     
            Skip a line and indent eight spaces.
            That's four spaces for the list
            and four to trigger the code block.
    

    If you need to do something that Markdown can't handle, use HTML. Note that we only support a very strict subset of HTML!

    Strikethrough humor is <strike>funny</strike>.
    

    Markdown is smart enough not to mangle your span-level HTML:

    <b>Markdown works *fine* in here.</b>
    

    Block-level HTML elements have a few restrictions:

    1. They must be separated from surrounding text by blank lines.
    2. The begin and end tags of the outermost block element must not be indented.
    3. Markdown can't be used within HTML blocks.

    <pre>
     You can <em>not</em> use Markdown in here.
    </pre>
    
 

Not the answer you're looking for? Browse other questions tagged or ask your own question.