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

C#导出DLL供Delphi调用:Marshal内存释放及字符串填充疑问

关于C#导出DLL给Delphi调用的内存释放疑问解答

嘿,关于你在C#导出DLL给Delphi调用时,Marshal.StringToHGlobalUni和Marshal.FreeHGlobal的使用疑问,我来帮你理清楚核心逻辑——跨语言调用的关键永远是明确内存所有权:谁分配,谁释放。

先拆解你的当前场景

你提到现在是让Delphi传入LPWSTR类型的宽字符串指针,由C#填充内容。这里首先要分两种情况来看:

情况1:Delphi预先分配好缓冲区(推荐方案)

如果这个LPWSTR指针指向的是Delphi已经分配好的足够大的内存缓冲区(比如Delphi里用SetLength给WideString分配了空间,再传指针),那你根本不需要用Marshal.StringToHGlobalUni!

这种场景下,C#只需要把字符串内容复制到Delphi提供的缓冲区里就行,内存所有权完全在Delphi那边,自然由Delphi负责释放,C#这边不用做任何Free操作。举个代码例子:

[DllExport]
public static void FillMessage(IntPtr lpBuffer, int bufferSize)
{
    string targetMessage = "你要填充的特定消息";
    // 确保不超出缓冲区大小,要给字符串终止符留位置
    int maxCharCount = Math.Min(targetMessage.Length, bufferSize - 1);
    // 把字符串内容复制到Delphi的缓冲区
    Marshal.Copy(targetMessage.ToCharArray(), 0, lpBuffer, maxCharCount);
    // 手动添加宽字符串的终止符(必须加,否则Delphi读取会出问题)
    Marshal.WriteInt16(lpBuffer, maxCharCount * 2, 0);
}

这种方式最安全,完全避免了跨语言内存释放的矛盾,也是跨语言调用里的常规做法。

情况2:你用Marshal.StringToHGlobalUni分配内存给Delphi用

如果你的逻辑是C#分配内存(比如用Marshal.StringToHGlobalUni把托管字符串转成非托管指针),再把这个指针交给Delphi,那就要特别注意:

  • Marshal.StringToHGlobalUni是在非托管堆上分配的内存,只有调用Marshal.FreeHGlobal才能释放它。
  • 绝对不能在C#的填充函数里直接调用FreeHGlobal,否则Delphi拿到的就是野指针,必然崩溃。

这种场景下有两种合规的处理方式:

  1. 给Delphi提供专门的释放函数
    额外导出一个函数让Delphi在使用完字符串后调用,由C#负责释放内存:

    [DllExport]
    public static void FreeAllocatedString(IntPtr strPtr)
    {
        if (strPtr != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(strPtr);
        }
    }
    

    Delphi那边拿到指针后,必须在使用完成后调用这个FreeAllocatedString,否则会造成内存泄漏。

  2. 用你的IDisposable类管理内存(有风险,需谨慎)
    如果你打算在实现IDisposable的类里释放这些内存,一定要注意:必须确保Delphi在C#类实例被Dispose之前,已经不再使用这块内存。
    比如在类的Dispose方法里释放所有通过StringToHGlobalUni分配的指针,但如果Delphi在Dispose之后还访问该指针,就会触发访问违规错误。这种方式只适合Delphi的使用周期完全依附于C#类实例生命周期的场景。

最后给你个最佳实践建议

优先选择让Delphi分配缓冲区,C#只负责写入的方案,这种方式内存所有权清晰,不会出现跨语言释放的混乱问题。如果确实需要C#分配内存,一定要和Delphi端明确约定释放规则,避免内存泄漏或野指针问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:10:46