Haskell DLL导致内存泄漏

我正在使用一个使用
Haskell DLL的C项目(GHC版本是8.0.1 x64).我注意到,执行程序消耗了大量内存.我调查了这件事,这就是我发现的.让我们考虑以下最小的例子.这是一个由三个文件组成的小项目.

HaskellExports.hs

{-# LANGUAGE ForeignFunctionInterface #-}
module HaskellExports where

import Foreign.C.Types
import Foreign.StablePtr

foreign export ccall foo :: CInt -> IO (StablePtr Int)

foo :: CInt -> IO (StablePtr Int)
foo (CInt n) = newStablePtr (fromIntegral n)

包含一个应该从C/C++代码调用的函数.

CWrapper.cpp

#define DLLExport extern "C" __declspec(dllexport) 

DLLExport void* c_smth (const int num)
{
    return 0;
}

我故意没有包含Haskell函数的实际导出,因为它们对这个例子没有任何影响.

main.cpp中

#include <Windows.h>

int main()
{
    for (;;)
    {
        HINSTANCE module = ::LoadLibrary(L"HaskellExports.dll");
        ::FreeLibrary(module);
    }
    return 0;
}

在这里,在无限循环中,我加载库并立即释放它.让我们尝试以两种不同的方式构建DLL.首先,我们不要包含Haskell对象文件:

ghc -c HaskellExports.hs
ghc -c CWrapper.cpp 
ghc -shared -no-hs-main -o HaskellExports.dll CWrapper.o

我运行该程序并注意到(在Windows进程监视器的帮助下),内存资源被正确捕获和释放.

现在让我们添加Haskell对象文件:

ghc -c HaskellExports.hs
ghc -c CWrapper.cpp 
ghc -shared -no-hs-main -o HaskellExports.dll CWrapper.o HaskellExports.o

我再次运行该程序并注意到,它在很长一段时间内消耗了越来越多的内存而无意释放它.这种情况导致崩溃.

我究竟做错了什么?

附:进一步的调查表明,只有当HaskellExport.hs包含至少一个外部导出函数时才会导致内存泄漏.

最佳答案 我决定发电子邮件到ghc-devs邮件列表. (要阅读所有通信,请参阅
the question和更多消息,答案可以在
here找到).

简要说明.内存泄漏是由于以下原因引起的:对于每个外部导出,RTS创建一个静态C包装器,它在DLL_PROCESS_ATTACH上初始化,但在DLL_PROCESS_DETACH期间没有终结器/析构函数.所以它会一直存在,直到程序终止.

点赞