Я работаю над проектом C ++, в котором используется библиотека Haskell (версия 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
Я снова запустил программу и заметил, что она все больше и больше потребляет памяти без намерения освободить ее. Эта ситуация приводит к краху.
Что я делаю не так?
P.S. Дальнейшие исследования показали, что утечка памяти возникает только тогда, когда HaskellExport.hs
содержит хотя бы одну foreign export
функцию.