Windows 7 上的 C++ 内存泄漏

Posted

技术标签:

【中文标题】Windows 7 上的 C++ 内存泄漏【英文标题】:C++ Memory leaks on Windows 7 【发布时间】:2014-01-28 21:43:52 【问题描述】:

我正在编写一个程序(C++,MinGW 32 位)来使用 OpenCV 函数批处理图像,使用 AngelScript 作为脚本语言。截至目前,我的软件有一些内存泄漏,这些内存泄漏很快就会增加(每个图像为 100-200 MB,我一次处理数千个)但我遇到了 Windows 似乎没有的图像正在释放我的程序使用的内存,直到重新启动。

如果我在大量图像上运行它,它会运行一段时间,最终 OpenCV 会抛出一个异常,说它内存不足。那时,我关闭程序,任务管理器的物理内存计量器回落到我开始之前的位置。但这里有一个问题 - 每次我尝试再次运行该程序时,它都会立即失败,无法为 OpenCV 分配内存,直到我重新启动计算机,此时它将再次适用于数百张图像。

Windows 是否可以通过某种方式保留该内存?或者是否还有其他原因导致 Windows 在重新启动之前无法为我的程序分配内存?这对我来说没有意义。

编辑: 我正在运行此程序的计算机是 Windows 7 64 位,具有 32 GB 内存,因此即使我的程序存在内存问题,它也只使用了少量可用内存.通常,该程序在退出之前会超过 1 GB 的内存。

编辑 2: 我也使用 FreeImage 来加载图像,我忘了提及。这是我的处理代码的基础:

//load bitmap with FreeImage
FIBITMAP *bitmap = NULL;
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
fif = FreeImage_GetFileType(filename.c_str(), 0);
bitmap = FreeImage_Load(fif, filename.c_str(), 0);
if (!bitmap) 
    LogString("ScriptEngine: input file is not readable.");
    processingFile = false;
    return false;

//convert FreeImage bitmap to my custom wrapper for OpenCV::Mat
ScriptImage img;
img.image = fi2cv(bitmap);
FreeImage_Unload(bitmap);

try 
    //this executes the AngelScript code
    r = ctx->Execute();
 catch(std::exception e) 
    std::cout << "Exception in " << __FILE__ << ", line " << __LINE__ << ", " << __FUNCTION__ << ": " << e.what() << std::endl;


try 
    engine->GarbageCollect(asGC_FULL_CYCLE | asGC_DESTROY_GARBAGE);
 catch (std::exception e) 
    std::cout << "Exception in " << __FILE__ << ", line " << __LINE__ << ", " << __FUNCTION__ << ": " << e.what() << std::endl;

如您所见,唯一的指针是指向已释放的 FIBITMAP。

【问题讨论】:

等等,一个图片是100mb?? 是的,这些图像是高分辨率未压缩的 TIFF。 你能提供一个最少的代码,或者至少是抛出异常的部分吗?你是如何读取和释放图像缓冲区的? 您确定是内存泄漏还是内存不足?仅当您已分配内存但不再持有对它的任何引用时,才会存在内存泄漏。这意味着这不是泄漏:vector&lt;double&gt; vec; for(int i = 0; i &lt; 10000000000000000000000; i++) vec.push_back(i); 虽然这段代码可能会消耗你所有的内存。 看起来 OpenCV 在 GPU 上工作,所以我猜不是 Windows 本身负责内存分配。我不知道OpenCL内存分配是如何工作的,进程退出时没有自动释放可能是正常的。这也可以解释为什么你的最大容量是 1GB,我猜你的显卡只有 1GB 内存。 【参考方案1】:

很可能您正在复制这一行的图像数据:

img.image = fi2cv(bitmap);

由于您在之后立即释放位图,因此该数据必须在释放后保留。

检查是否有 ScriptImage 对象的资源释放。

【讨论】:

该函数只使用 cv::Mat 对象,不分配任何内存,所以应该没有问题。但是,我的问题不是为什么内存泄漏(我知道它是),而是为什么我的程序内存不足导致的行为似乎一直持续到我重新启动 Windows。 您正在使用的库中可能存在运行时元素。您可能能够看到它并使用 windows 任务资源管理器或 SysInternals Process Explorer 结束任务。 “运行时元素”是什么意思?如果您的意思是其中一个库正在启动另一个进程,我认为这不太可能。 必须有其他东西在运行。 Windows 将内存与 Windows 进程隔离开来。如果您的程序退出后 仍然存在内存泄漏,则系统中有另一个进程持有该内存。获取process explorer 的副本并使用它来检查系统中运行的所有内容。它有一个选项卡,用于显示计算机上运行的每个进程(和线程)正在使用的私有字节或内存。 (此工具显示的内容远远超过 Windows 任务管理器。) 这不是完全正确的;内存可能被内核模式组件占用,例如 GPU 驱动程序或防病毒软件,或者 OpenCV 可能错误地报告了问题的实际原因,并且实际上没有任何内存丢失。它几乎必须是这三种可能性之一,但任何人都在猜测。 :-)

以上是关于Windows 7 上的 C++ 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Unity - Android, C# - C++ 内存泄漏

在 Visual C++ (Windows) 中检测内存泄漏

C++ 智能指针

ubuntu上的python2.7函数范围()内存泄漏

一个跨平台的 C++ 内存泄漏检测器

转储内存以查找 C++ 应用程序中的内存泄漏