c# - 堆已损坏。 C# dllimport、delphi PChar返回值

标签 c# delphi dllimport

我已经导入了 dll。所有其他部分都有效,但导入方法的字符串返回值给出了这个:

Unhandled exception at 0x7748EA5F (ntdll.dll) in ***.exe: 0xC0000374: A heap has been corrupted (parameters: 0x774C4270).

它仍然会返回字符串,但我担心这会导致以后出现一些难以调试的其他错误。根据我的测试,感觉它可以是任何东西,这就是造成这种情况的原因。

这是我的导入代码:

[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
private delegate String GetStringDelegate(int handle, int index);

private static GetStringDelegate getString { get; set; }

var addressOfGetString = NativeMethods.GetProcAddress(_handle, "GetString");
getString = (GetStringDelegate)Marshal.GetDelegateForFunctionPointer(addressOfGetString, typeof(GetStringDelegate));

用法

getString(Handle, 1);

这有效,但会导致错误。调试时,只需按“继续”即可让它处理并显示结果。结果正确。

在delphi dll中是这样实现的

function GetString(Hnd,Index : Integer) : PChar; stdcall;
begin
 Result:=TControl(Hnd).Stack.GetString(Index);
end;

我对整数、 double 、 bool 值和 dll 中的所有其他东西都有相同类型的代码,没有错误。所以我认为它会造成某种溢出或错误的内存分配大小。

注意:如果我创建控制台应用程序,它只会失败,不会因错误而中断,如果我在没有调试器 ( ctrl+f5 ) 的情况下运行控制台,它会工作,但仍然没有错误。当我从表单应用程序调用它时生成堆错误。

长话短说;此代码有效,但它显示堆错误,同时返回 int、bool 等完美无缺。

最佳答案

当您返回一个字符串作为 p/invoke 函数的函数返回值时,编码器负责释放该内存。它假定内存是在 COM 堆上分配的,例如使用 CoTaskMemAlloc。您的字符串不符合该要求。

  • 您可以更改 Delphi 代码以那样分配内存。
  • 您可以返回 IntPtr 并使用 Marshal.PtrToStringAnsi 手动编码(marshal)。问题仍然是是否需要释放内存,如果需要如何释放。
  • 您可以返回一个 COM BSTR,但这仅适用于 Delphi 作为输出参数而不是函数返回值。参见 Why can a WideString not be used as a function return value for interop?
  • 您可以要求调用者分配内存并让被调用者填充它。

我不能肯定地看到你的代码,但如果你返回 PChar(s) 我不会感到惊讶,其中 s 是一个局部变量.这意味着您将返回已释放内存的地址。

这里的底线是,从被调用方到调用方传递字符串(或者实际上是数组或其他动态结构)比传递简单的值类型要复杂得多。您将需要重新考虑如何执行此操作。

关于c# - 堆已损坏。 C# dllimport、delphi PChar返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30349296/

相关文章:

c# - 在基类中使用动态关键字和调用泛型方法导致 StackOverflowException

c# - MongoDB 中的运算符使用官方 .NET 驱动程序执行多过滤器查询

delphi - 阅读当前项目Delphi 2010的数据版本

forms - 在 Delphi 中对于模态表单使用 Free 而不是 Release 安全吗?

c# - 检测到缓冲区溢出

c# - 在哪里放置非托管 DLL 以用于导入 C# 程序?

c# - 从数据库中选择指定日期范围内的数据

c# - 在 SQL 中基于一对多表关系填充对象

德尔福XE6。 [dcc32 fatal error ] F2438 UCS-4 文本编码不受支持。转换为 UCS-2 或 UTF-8

c# - 向按钮添加 UAC 屏蔽并保留其背景图像?