在运行时检测 C++ 中的堆碎片的便携式方法?

Posted

技术标签:

【中文标题】在运行时检测 C++ 中的堆碎片的便携式方法?【英文标题】:Portable way to detect heap fragmentation in c++ at runtime? 【发布时间】:2010-11-30 00:40:05 【问题描述】:

我正在编写一个基于 qt 的 c++ 应用程序,我需要能够检测内存碎片,以检查当前系统是否能够实际承受内存负载:程序加载一个大图像(15/21 兆像素是规范)在内存中,然后对其执行一些过滤(w/稀疏矩阵)。 例如,我在 Windows 中遇到内存碎片问题,而 VMMap 在这方面非常有帮助:问题是一些 DLL(Wacom 平板电脑“wintab32.dll”和 UltraMon 应用程序)没有重新定位,所以拆分地址空间在进程的 0x10000000-0x30000000 VA 处。

我想为应用程序提供对碎片问题的某种认识,并想知道是否已经存在提供 VMMAP 提供的信息的跨平台 (linux/mac/win32) 方法。

【问题讨论】:

要挑剔:堆的存在是一个实现细节,C++参考free-store。 你是对的,但我是故意这样做的,因为“堆”似乎是一个更普遍接受的术语;) 这不仅仅是术语的不同。免费商店根本不需要堆。然而,这只是实现决定解决内存分配请求。 【参考方案1】:

简短回答:没有可移植的方式。

更长的答案:堆的实现方式和工作方式是您实现的实现细节,在平台、标准库和操作系统之间存在很大差异。您必须为每个实现创建一个不同的版本 - 前提是,该实现为您提供了一个 API 来挂钩它。 (我认为应该是你所针对的三个平台的情况。)

【讨论】:

【参考方案2】:

我认为你过于悲观了。 21 兆像素,即使假设色深为 16 位和相同大小的 alpha 通道也只需要 168 MB。 32 位系统上的可用地址空间以千兆字节为单位。

【讨论】:

由于精度是必须的,图像在内存中以浮点值(32 位)表示,并且始终存在三个通道(RGB 或 CiELab)导致 252MB,但这不是重点。有时应用程序以 1.4Gb 的最大可分配块开始,有时只有 500Mb,在较低 VA 处导致大部分碎片的 DLL 是在 0x10000000 处加载的“wintab32.dll”。 32 位系统上的可用地址空间以千兆字节为单位,但如果您有 3gb 的总空闲小块并不重要,碎片会导致 4gb-ram 机器上的 bad_alloc... 不幸的是,似乎一旦 DLL 在 0x10000000 处加载,所有其他 DLL 都会重新定位在该 VA 附近:禁用 Wacom 数位板可以让其他 DLL 被推到上层,但只要下层限制被使用,然后其他 DLL(例如 uxtheme.dll)在它附近被加载。 如果您不介意更改 DLL,您可以更改其首选库。 0x10000000 现在是一个特别糟糕的默认值。 没错,一个很的选择,可惜这个DLL不能rebase(rebase -v -b 0x10000000 wintab32.dll说不能rebase)。【参考方案3】:

这可以满足您的需要吗?

bool is_contiguous_freestore_available(size_t max)

   char* tst = new(std::nothrow) char[max];
   if (tst == null)
      return false;

   delete[] tst;
   return true;

【讨论】:

不是真的,因为我想检测这种情况,虽然“工作”,但这样做可能会很好地分割内存本身。

以上是关于在运行时检测 C++ 中的堆碎片的便携式方法?的主要内容,如果未能解决你的问题,请参考以下文章

用户 DLL/EXE 中的堆分配失败

将数组分配到运行时已知大小的堆上

java中的堆和栈

有没有办法处理 AVR/Arduino 微控制器中的堆内存碎片?

C++分段错误中的堆算法

java - 如何在java中的堆上单独获取所有对象消耗的运行时内存