39

Is it possible, for a c++ program, to track how much memory the program is using at one time?

For example, a function with a prototype:

int getEstimatedTotalMemoryUsage(); 

I suppose if it's not possible, then one will have to get out of the program, do a system call and check the results from there. If so, what tools are available for such purposes? Assuming such a thing is possible, that is.

edit: I'm using linux, any tools that can do this for you?

1

4 Answers 4

38

Yes - use POSIX getrusage. From the Linux man page:

Synopsis

#include <sys/time.h> #include <sys/resource.h> int getrusage(int who, struct rusage *usage); 

Description

getrusage() returns current resource usages, for a who of either RUSAGE_SELF or RUSAGE_CHILDREN. The former asks for resources used by the current process, the latter for resources used by those of its children that have terminated and have been waited for.

struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary context switches */ }; 
Sign up to request clarification or add additional context in comments.

6 Comments

And for GNU/Linux, this is the struct rusage: gnu.org/s/libc/manual/html_node/Resource-Usage.html
Anything similar for Windows?
"Not all fields are meaningful under Linux. In Linux 2.4 only the fields ru_utime, ru_stime, ru_minflt, and ru_majflt are main- tained. Since Linux 2.6, ru_nvcsw and ru_nivcsw are also maintained. "
Good catch, @Jay - I use getrusage() on my mac all the time, and I didn't even think it might not be fully implemented on Linux. Is there an alternative source of information for the OP? Clearly I should have read the whole man page...
Ah, so ixrss, idrss etc which (I'm guessing) would be about memory not implemented on linux?
|
5

Here is an example of measuring memory used by process on Windows.

#include <windows.h> #include <Psapi.h> // [...] PROCESS_MEMORY_COUNTERS memCounter; BOOL result = K32GetProcessMemoryInfo(GetCurrentProcess(), &memCounter, sizeof(memCounter)); std::cout << "WorkingSetSize " << memCounter.WorkingSetSize << std::endl; 

And explanations of returned values https://learn.microsoft.com/en-gb/windows/win32/api/psapi/ns-psapi-process_memory_counters

Comments

2

I wanted this today, myself, so sharing the tested results here. I believe a call to getmem() will do what the OP asked, on any unix box. Written in very generic C, it will work in C or C++.

// Calling function must free the returned result. char* exec(const char* command) { FILE* fp; char* line = NULL; // Following initialization is equivalent to char* result = ""; and just // initializes result to an empty string, only it works with // -Werror=write-strings and is so much less clear. char* result = (char*) calloc(1, 1); size_t len = 0; fflush(NULL); fp = popen(command, "r"); if (fp == NULL) { printf("Cannot execute command:\n%s\n", command); return NULL; } while(getline(&line, &len, fp) != -1) { // +1 below to allow room for null terminator. result = (char*) realloc(result, strlen(result) + strlen(line) + 1); // +1 below so we copy the final null terminator. strncpy(result + strlen(result), line, strlen(line) + 1); free(line); line = NULL; } fflush(fp); if (pclose(fp) != 0) { perror("Cannot close stream.\n"); } return result; } int getmem() { pid_t pid = getpid(); char cmd[64]; snprintf(cmd, 64, "/bin/ps -p %d -o size", pid); char* result = exec(cmd); if (!result) { return 0; } // Find first newline. int pos = 0; while (result[pos] != '\n') { pos++; } // Remove the final newline. result[strlen(result) - 1] = '\0'; // Convert to integer. int size = atoi(result + pos + 1); free(result); return size; } 

Technically, I suppose the printf(...) line should be fprintf(stderr, ...), but I tend to have stderr redirected for certain environment-specific logging reasons, and this is how I compiled and tested the code, so I'm copying verbatim to avoid breakage.

Comments

1

Get your PID: pid_t getpid(void); // unistd.h

Parse /proc/<id>/smaps

If you don't care about shared libraries in mem total it may be simpler

make a system call to ps -p <id> -o %mem

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.