Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically check memory use in a fairly portable way? (C/C++)

I'm writing cross platform C++ code (Windows, Mac). Is there a way to check how much memory is in use by the current process? A very contrived snippet to illustrate:

unsigned long m0 = GetMemoryInUse();
char *p = new char[ random_number ];
unsigned long m1 = GetMemoryInUse();
printf( "%d bytes used\n", (m1-m0) );

Of course (m1-m0) should equal random_number, but I'm trying to do this on a more complicated level, including possible library calls that could allocate memory.

The following are not preferable:

  1. Use Valgrind (or its ilk)
  2. Use a custom memory allocator to track allocated memory.
like image 703
Patrick Hogan Avatar asked Dec 16 '08 19:12

Patrick Hogan


3 Answers

Here's some code I wrote to try to do this in a portable way. It's not perfect, but I think it should at least give a pointer to how to do this on each of several platforms.

(P.S. I use OSX and Linux regularly, and know this works well. I use Windows more rarely, so caveats apply to the Windows clause, but I think it's right.)

#ifdef __linux__
# include <sys/sysinfo.h>
#endif

#ifdef __APPLE__
# include <mach/task.h>
# include <mach/mach_init.h>
#endif

#ifdef _WINDOWS
# include <windows.h>
#else
# include <sys/resource.h>
#endif

/// The amount of memory currently being used by this process, in bytes.
/// By default, returns the full virtual arena, but if resident=true,
/// it will report just the resident set in RAM (if supported on that OS).
size_t memory_used (bool resident=false)
{
#if defined(__linux__)
    // Ugh, getrusage doesn't work well on Linux.  Try grabbing info
    // directly from the /proc pseudo-filesystem.  Reading from
    // /proc/self/statm gives info on your own process, as one line of
    // numbers that are: virtual mem program size, resident set size,
    // shared pages, text/code, data/stack, library, dirty pages.  The
    // mem sizes should all be multiplied by the page size.
    size_t size = 0;
    FILE *file = fopen("/proc/self/statm", "r");
    if (file) {
        unsigned long vm = 0;
        fscanf (file, "%ul", &vm);  // Just need the first num: vm size
        fclose (file);
       size = (size_t)vm * getpagesize();
    }
    return size;

#elif defined(__APPLE__)
    // Inspired by:
    // http://miknight.blogspot.com/2005/11/resident-set-size-in-mac-os-x.html
    struct task_basic_info t_info;
    mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
    task_info(current_task(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
    size_t size = (resident ? t_info.resident_size : t_info.virtual_size);
    return size;

#elif defined(_WINDOWS)
    // According to MSDN...
    PROCESS_MEMORY_COUNTERS counters;
    if (GetProcessMemoryInfo (GetCurrentProcess(), &counters, sizeof (counters)))
        return counters.PagefileUsage;
    else return 0;

#else
    // No idea what platform this is
    return 0;   // Punt
#endif
}
like image 91
Larry Gritz Avatar answered Nov 12 '22 21:11

Larry Gritz


I've used SIGAR API to get all sorts of system related info quite portably across major platforms. It's open source (Apache) as well. There is really no need to reinvent the wheel on these relatively trivial but tedious work.

like image 3
ididak Avatar answered Nov 12 '22 19:11

ididak


  • There is no portable way to do that.
  • For most Operating systems, there isn't even a reliable way to do it specific to that OS.
like image 2
James Curran Avatar answered Nov 12 '22 20:11

James Curran