You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ DLL分配内存是否会被C#回收?stb_image互操作疑问

关于Unity中C++ stb_image与.NET互操作的内存问题解答

问题1:.NET垃圾回收是否会提前释放C++分配的内存?

不会。IntPtr本质只是一个存储内存地址的数值类型,.NET的垃圾回收器(GC)完全不知道这块内存是在C++堆上分配的,所以它既不会主动释放这块内存,也不会移动或覆盖它的内容。只要你自己不调用释放函数,这块内存会一直保留在C++堆中,直到进程结束或者你显式释放,后续保存图像文件的操作不会被GC干扰。

问题2:能否通过C#传递IntPtr调用stbi_image_free来正确释放内存?

完全可以,只要在C++侧正确封装stbi_image_free函数即可。

补充完整的代码实现:

C++侧代码

#include "stb_image.h"

__declspec(dllexport) unsigned char* GetImage(const char* filename, int* width, int* height, int* comp) {
    return stbi_load(filename, width, height, comp, 0);
}

__declspec(dllexport) void FreeImage(unsigned char* data) {
    stbi_image_free(data);
}

C#侧DllImport封装

public static class ImageReader
{
    [DllImport("YourCppDllName.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetImage(string filename, ref int width, ref int height, ref int comp);

    [DllImport("YourCppDllName.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void FreeImage(IntPtr data);

    public static TextureFormat FormatFromPixelComponents(int comp)
    {
        switch(comp)
        {
            case 3: return TextureFormat.RGB24;
            case 4: return TextureFormat.RGBA32;
            default: return TextureFormat.RGB24;
        }
    }
}

C#侧使用示例(补充释放逻辑)

int width = 0, height = 0;
int pixelComponents = 0;

IntPtr ptr = ImageReader.GetImage(path, ref width, ref height, ref pixelComponents);

if (ptr == IntPtr.Zero) throw new Exception("Error loading image");

try
{
    Texture2D ex = new Texture2D(width, height, ImageReader.FormatFromPixelComponents(pixelComponents), false);
    ex.LoadRawTextureData(ptr, width * height * pixelComponents);
    ex.Apply(); // Sends texture to GPU

    // 执行保存图像文件的操作
    byte[] imageBytes = ex.EncodeToPNG();
    File.WriteAllBytes(Path.Combine(Application.persistentDataPath, "saved.png"), imageBytes);
}
finally
{
    // 无论是否出错,都要释放内存避免泄漏
    ImageReader.FreeImage(ptr);
}

关键注意事项

  • 必须确保传递给FreeImage的IntPtr是GetImage返回的、由stbi_load分配的内存地址,传入其他指针会导致未定义行为(比如程序崩溃)。
  • 用try-finally块包裹内存使用逻辑,确保异常场景下也能释放内存,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Gwendolyn Krezel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:33:15