堆已损坏。 C# dllimport,delphi PChar return 值

A heap has been corrupted. C# dllimport, delphi PChar return value

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

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

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

这是我的导入代码:

[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);

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

这是在 delphi dll

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

我有相同类型的整数、双精度、布尔值和 dll 中的所有其他代码,没有错误。所以我认为它会造成某种溢出或错误的内存分配大小。

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

TL;DR;此代码有效,但显示堆错误,而 returning ints、bools 等完美运行。

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

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

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

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