FreeLibrary在VC14上泄漏但在VC9上没有泄漏

时间:2017-05-29 14:22:00

标签: c windows visual-c++ memory-leaks

我正在使用第三方库,它显然存在我们在从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并没有真正帮助我,尽管一个答案暗示了一些黑客的解决方案。

我做了一个最小的工作示例,以表明它不是特定于库。首先,我在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。

1 个答案:

答案 0 :(得分:0)

真正的问题是VC9无意中释放了一个合理的程序可能仍然存在的内存 - 毕竟,free()没有被调用。当然,这是CRT无法让所有人满意的领域之一 - 您想要自动free行为。

这是因为FreeLibrary是一个非常简单的Win32函数。它从您的地址空间中删除了一大块代码。您可能会收到DllMain的最终来电,但正如DllMain的文档说明:您在那里做不了多少。除了DLL的代码和数据段之外,有一点特别困难的是找出需要释放的内存。