在 C++ 中使用 C# dll 时内存泄漏

Memory leak while using C# dll in a C++

情况是,我包装了C# dll 以在C++ 项目中使用它,当我执行C++ 项目时,我看不到任何内存泄漏的迹象,但内存逐渐增加。我认为这是因为 C# 库中的 GC 在 C++ 项目中不起作用,我不知道如何解决它。请帮助我。

我的代码如下:

  1. C#
    using Microsoft.Win32.SafeHandles;
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    namespace CSharpLib
    {

        [Guid("8EA9EAA8-CA3D-4584-B1E0-7B9561757CA4")]
        public interface ICSharpLibrary
        {
            int[] GetData();
            string GetName();
            bool Init();
        }

        [Guid("B62A2B51-621D-41AA-8F4F-021E404B593C")]
        public class CSharpLibrary : ICSharpLibrary, IDisposable
        {
            private bool disposed = false;

            private int[] data;

            private string name = "CSharpLib";

            private SafeHandle safeHandle = new SafeFileHandle(IntPtr.Zero, true);

            private void MakeData()
            {
                var list = new List<int>();
                var rnd = new Random();
                for(var i = 0; i < 1000; i++)
                {
                    list.Add(rnd.Next(0, 255));
                }
    
                data = list.ToArray();
            }
    
            public int[] GetData()
            {
                MakeData();
                return data;
            }
    
            public string GetName()
            {
                return name;
            }
    
            public bool Init()
            {
                data = null;
    
                return true;
            }
    
            public void Dispose()
            {
                Dispose(true);
            }
    
            protected virtual void Dispose(bool disposing)
            {
                if (disposed)
                {
                    return;
                }
                if (disposing)
                {
                    data = null;
                    safeHandle.Dispose();
                }
    
                disposed = true;
            }
        }
    }
  1. C++

    #pragma once
    
    #ifdef CPLUSLIBRARY_EXPORTS
    #define CPLUSLIBRARY_API __declspec(dllexport)
    #else
    #define CPLUSLIBRARY_API __declspec(dllimport)
    #endif
    
    extern "C" CPLUSLIBRARY_API bool Init();
    
    extern "C" CPLUSLIBRARY_API int* GetData();
    
    extern "C" CPLUSLIBRARY_API char* GetName();

    #include <Windows.h>
    #include "pch.h"
    #include "CPlusLibrary.h"
    
    #import "lib/CSharpLibrary.tlb" no_namespace named_guids
    
    ICSharpLibrary* lib = NULL;
    int* data = NULL;
    bool isWorking = false;
    char* name = NULL;
    
    bool Init() {
        HRESULT hr = CoInitializeEx(NULL, tagCOINIT::COINIT_MULTITHREADED);
    
        if (!SUCCEEDED(hr))
            return false;
    
        hr = CoCreateInstance(CLSID_CSharpLibrary, NULL, CLSCTX_INPROC_SERVER, IID_ICSharpLibrary, reinterpret_cast<void**>(&lib));
    
        if (!SUCCEEDED(hr))
            return false;
    
        return true;
    }
    
    int* GetData() {
        auto raw = lib->GetData();
        void* pVoid = NULL;
    
        HRESULT hr = ::SafeArrayAccessData(raw, &pVoid);
    
        if (!SUCCEEDED(hr))
            return NULL;
        auto result = reinterpret_cast<int*>(pVoid);
    
        return result;
    }
    
    char* GetName() {
        char str[10];
        strcpy_s(str, lib->GetName());
        name = str;
    
        return name;
    }
  1. 执行者
    #include <iostream>
    #include <CPlusLibrary.h>
    #include <CoreWindow.h>
    
    int main()
    {
        if (!Init())
            return 0;
    
        while (true) {
            auto name = GetName();
            std::cout << name << std::endl;
            auto data = GetData();
    
            for (int i = 0; i < 1000; i++) {
                std::cout << data[i];
            }
    
            std::cout << std::endl;
    
            Sleep(100);
        }
    }

来自SafeArrayAccessData documentation

After calling SafeArrayAccessData, you must call the SafeArrayUnaccessData function to unlock the array.

不确定这是泄漏的真正原因。但是在调试问题时,一个好的第一步是确保您遵循文档中指定的所有规则。