我正在使用第三方库,它显然存在我们在从Visual Studio 2008(VC9.0)升级到Visual Studio 2015(VC14.0)时首次发现的内存泄漏。在Windows上,我使用LoadLibrary在运行时加载库,完成使用后,我使用FreeLibrary卸载它。当使用VC14.0编译和链接时,库中分配的所有内存在使用VC14.0时在FreeLibrary上释放,但一些内存永远不会释放。下面我的测试程序的内存配置文件可以在这里看到:http://imgur.com/a/Hmn1S。VC14上FreeLibrary泄漏,但VC9上泄漏
为什么VC9.0和VC14.0的行为不同?并且可以在不改变库的来源的情况下做任何事情来避免泄漏,就像模仿VC9.0的行为一样?
我可以在这里找到的唯一一件事是:Memory leaks on DLL unload这并没有真正帮助我,尽管一个答案暗示了一些hacky解决方案。
我做了一个最小的工作示例,以表明它不是特定于库。首先,我创建用C与分配一些内存功能的小型图书馆,从来没有解除分配:
leaklib.h:
#ifndef LEAKLIB_H_
#define LEAKLIB_H_
__declspec(dllexport) void leak_memory(int memory_size);
#endif
leaklib.c:
#include "leaklib.h"
#include <stdio.h>
#include <stdlib.h>
void leak_memory(int memory_size)
{
double * buffer;
buffer = (double *) malloc(memory_size);
if (buffer != NULL)
{
printf("Allocated %d bytes of memory\n", memory_size);
}
}
然后用一个程序加载库,调用内存泄漏函数,然后再次卸载库 - 反复,以便我们可以跟踪内存随着时间的推移。
memleak.c:从任VS9.0或
cl.exe /MTd /LD leaklib.c
,并且程序用
cl.exe memleak.c
与cl.exe时:
#include <windows.h>
#include <stdio.h>
int main(void)
{
int i;
HINSTANCE handle;
int load_success;
void (*leak_memory)(int);
int dll_unloaded;
Sleep(30000);
for (i = 0; i < 100; ++i)
{
handle = LoadLibrary(TEXT("leaklib.dll"));
leak_memory = GetProcAddress(handle, "leak_memory");
printf("%d: leaking memory...\n", i);
leak_memory(50*1024*1024);
printf("ok\n\n");
Sleep(3000);
dll_unloaded = FreeLibrary(handle);
if (!dll_unloaded)
{
printf("Could not free dll'");
return 1;
}
Sleep(3000);
}
return 0;
}
我然后生成与库VS14.0。
之前在VS2012中使用的CRT版本有隐藏内存泄漏错误的诀窍,他们用HeapCreate()创建了自己的堆。但是现在没有更多的分配是通过默认进程堆进行的,即GetProcessHeap()返回的进程堆。 –
但你没有释放由'leak_memory'分配的内存 - 因此泄漏并且必须在这里 – RbMm
正如你能够在没有库的情况下重现:你为什么怀疑它是在这个库中?为什么你会用两种不同的语言重复标记?如果这是C,请不要投放'malloc'和朋友的结果。删除不相关的标签。 – Olaf