简体   繁体   English

如何从 C++ 程序内部测量内存使用情况?

[英]How to measure memory usage from inside a C++ program?

Is it possible, for a c++ program, to track how much memory the program is using at one time?对于 C++ 程序,是否有可能跟踪该程序一次使用了多少内存?

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?编辑:我正在使用 linux,有什么工具可以为您做到这一点?

Yes - use POSIX getrusage .是 - 使用 POSIX getrusage From the Linux man page :Linux 手册页

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 . getrusage()返回当前的资源使用,对于无论是RUSAGE_SELFRUSAGE_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 */ };

Here is an example of measuring memory used by process on Windows.这是在 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://docs.microsoft.com/en-gb/windows/win32/api/psapi/ns-psapi-process_memory_counters以及返回值的解释https://docs.microsoft.com/en-gb/windows/win32/api/psapi/ns-psapi-process_memory_counters

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.我相信在任何 unix 机器上调用 getmem() 都会执行 OP 的要求。 Written in very generic C, it will work in C or C++.用非常通用的 C 编写,它可以在 C 或 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.从技术上讲,我认为 printf(...) 行应该是 fprintf(stderr, ...),但由于某些特定于环境的日志记录原因,我倾向于将 stderr 重定向,这就是我编译和测试代码的方式,所以我正在逐字复制以避免破损。

Get your PID: pid_t getpid(void); // unistd.h获取你的PID: pid_t getpid(void); // unistd.h pid_t getpid(void); // unistd.h

Parse /proc/<id>/smaps解析/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 %memps -p <id> -o %mem进行系统调用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM