【发布时间】:2017-10-29 21:35:18
【问题描述】:
我使用的第三方库显然存在内存泄漏,这是我们在从 Visual Studio 2008 (VC9.0) 升级到 Visual Studio 2015 (VC14.0) 时首次发现的。在 Windows 上,我在运行时使用 LoadLibrary 加载库,使用完毕后,我使用 FreeLibrary 卸载它。使用 VC9.0 编译和链接时,库分配的所有内存都会在 FreeLibrary 上释放,而使用 VC14.0 时,某些内存永远不会释放。下面我的测试程序的内存配置文件可以在这里看到:http://imgur.com/a/Hmn1S。
为什么 VC9.0 和 VC14.0 的行为不同?是否可以在不改变库源的情况下做任何事情来避免泄漏,比如模仿 VC9.0 的行为?
我在 SO 上唯一能找到的是: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:
#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;
}
然后我构建库:
cl.exe /MTd /LD leaklib.c
和程序
cl.exe memleak.c
使用来自 VS9.0 或 VS14.0 的 cl.exe。
【问题讨论】:
-
在 VS2012 中使用的 CRT 版本具有隐藏内存泄漏错误的诀窍,他们使用 HeapCreate() 创建了自己的堆。但仅此而已,现在从默认进程堆(由 GetProcessHeap() 返回的堆)进行分配。
-
但是你没有释放
leak_memory分配的内存——所以泄漏并且必须在这里 -
因为您可以在没有库的情况下进行复制:您为什么怀疑它在那个库中?你为什么要双重标记为两种不同的语言?如果那是 C,请不要转换
malloc和朋友的结果。删除不相关的标签。
标签: c windows visual-c++ memory-leaks