【问题标题】:How do I programmatically check memory use in a fairly portable way? (C/C++)如何以相当可移植的方式以编程方式检查内存使用情况? (C/C++)
【发布时间】:2008-12-16 19:54:52
【问题描述】:

我正在编写跨平台 C++ 代码(Windows、Mac)。有没有办法检查当前进程正在使用多少内存?一个很做作的sn-p来说明:

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

当然 (m1-m0) 应该等于 random_number,但我正在尝试在更复杂的级别上执行此操作,包括可能分配内存的库调用。

以下是不可取的:

  1. 使用 Valgrind(或其同类)
  2. 使用自定义内存分配器来跟踪 分配的内存。

【问题讨论】:

  • 查看 mallinfo()。

标签: c++ memory portability


【解决方案1】:

这是我编写的一些代码,试图以可移植的方式执行此操作。它并不完美,但我认为它至少应该指出如何在多个平台上执行此操作。

(P.S. 我经常使用 OSX 和 Linux,并且知道这很好用。我很少使用 Windows,所以注意事项适用于 Windows 子句,但我认为它是正确的。)

#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
}

【讨论】:

  • 在#elif defined(APPLE)之前的行中有一个杂散的#endif。
  • 不幸的是,它似乎不起作用。 :( 我挖掘得越多,似乎没有自定义内存管理器就没有什么好方法了。
  • @pbhogan 我会坚持使用上述平台相关代码。上面的代码有点混乱,但它应该为您提供一个良好的开端(windows 部分有一个错误 - 计数器!= 计数,请参阅msdn.microsoft.com/en-us/library/ms683219(VS.85).aspx 和链接示例)。
  • @pbhogan 至于不会给你堆栈大小、系统保留内存、库分配内存等的自定义内存管理器......它是一个新项目吗?为什么需要这个?
  • Windows 定义应该是_WIN32_WINDOWS 默认情况下只为 DLL 和 GUI EXE 定义,控制台应用程序没有得到_WINDOWS,因为它没有预定义;参考msdn.com/library/b0084kay
【解决方案2】:

我使用SIGAR API 在主要平台上非常便携地获取各种系统相关信息。它也是开源的(Apache)。对于这些相对琐碎但乏味的工作,真的没有必要重新发明轮子。

【讨论】:

    【解决方案3】:
    • 没有便携的方法可以做到这一点。
    • 对于大多数操作系统,甚至没有一种可靠的方法可以针对该操作系统执行此操作。

    【讨论】:

    • 你可能是对的。我只是希望有一些我错过的东西。 :) 我很可能最终会使用自定义内存管理器。
    【解决方案4】:

    您可以使用“内存池”模式。程序中的所有对象都从该池中分配/取消分配内存,这样您就可以了解您消耗了多少内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-21
      • 2020-07-30
      • 1970-01-01
      • 2013-05-05
      • 1970-01-01
      • 2013-08-29
      相关资源
      最近更新 更多