gpt4 book ai didi

c# - 在 C# 中调用 Delphi COM 对象抛出 AccessViolationException

转载 作者:太空宇宙 更新时间:2023-11-03 14:47:06 30 4
gpt4 key购买 nike

我试图将一个字符串发送到 Delphi COM 对象并期望从该对象得到一个答案,但由于某种原因它抛出一个 AccessViolationException。这是它抛出的异常,翻译成英文的异常描述是:Attempted to read or write protected memory。这通常表明其他内存已损坏。程序输出(带有栈顶跟踪):

QManservice started.
Press any key to stop.
Request to get orders received.
String received: S$GET ORDERS,

Onnverwerkte uitzondering: System.AccessViolationException: Poging tot het lezen of schrijven van beveiligd geheugen. Dit duidt er vaak op dat ander geheugen is beschadigd.

bij Microsoft.Win32.Win32Native.SysStringByteLen(IntPtr bstr)
bij System.StubHelpers.BSTRMarshaler.ConvertToManaged(IntPtr bstr)
bij QMan_SafanDarley.IWLM_.Send(String Msg, String& Answer)
bij WorkLoadManagerServiceDefinitions.QManService.SendStringtoCON(String codToSend) in D:\Michael\C# Projects\QManServiceConsoleApp\OrderEditor_WCF\QManService.cs:regel 210
bij WorkLoadManagerServiceDefinitions.QManService.RequestGetOrders() in D:\Michael\CR Projects\QManServiceConsoleApp\OrderEditor_WCF\QManService.cs:regel 67 ...

这是调用COM的代码

private string SendStringToCOM(string cmdToSend)
{
try
{
Console.WriteLine($"String received: {cmdToSend}");
if (WLM == null)
{
WLM = new WLM_();
}
string answer = string.Empty;
WLM.Send(cmdToSend, out answer);
Console.WriteLine("Answer received");
return answer;
} catch(Exception e)
{
Console.WriteLine(e.Message);
Console.ReadKey();
return string.Empty;
}
}

这是 Delphi 中接收调用的代码,它将调用发送到另一个单元,该单元根据接收到的命令执行数据库操作。

function TWLM_.Send(const Msg: WideString; out Answer: WideString) : Integer;
begin
Result := fmProduction.AnalyzeData(Msg, 0);
end;

我应该补充一点,这适用于我的电脑和同事的电脑,但不适用于第三台电脑。关于如何解决这个问题有什么建议吗?

最佳答案

function TWLM_.Send(const Msg: WideString; out Answer: WideString) : Integer;
begin
Result := fmProduction.AnalyzeData(Msg, 0);
end;

这里您没有为 Answer 参数分配任何内容。这是作为 out 参数传递的,这意味着该方法需要为其分配一些内容。这与函数返回值的行为完全相同。

如果您不为该变量分配任何内容,那么在该方法为其分配堆栈空间时,它将具有恰好存在于堆栈中的任何(未分配的)值。这将不是指向 WideString 的有效指针,但使用代码会尝试将其编码,就好像它是一样。有时这会立即崩溃,有时不会,有时它可能只是破坏其他数据。无论哪种情况,都是错误。

在 native Delphi 代码中,您可能习惯于 outvar 参数 behaving quite similarly - 在这两种情况下,对于引用类型,调用代码的指针都可以通过接受参数的方法进行读写。如果该方法选择不修改它不需要的值。但是,对于托管互操作,期望的是 out 参数将始终由该方法分配。 C# 强制执行此操作,但 Delphi 不执行此操作。

在这种情况下,您在 C# 端传入的空字符串根本不会传入该方法 - 您可能希望它应该保持为空字符串,未被 Delphi 代码修改,但是通过将参数设为out 参数调用代码期望在该参数中接收一个返回值,并立即用返回的任何内容覆盖传递的变量(在这种情况下,指向无意义的指针)。 C# 端的变量在传递给此方法之前可能具有的任何值,推而广之,将无法在 Delphi/COM 端访问。

关于c# - 在 C# 中调用 Delphi COM 对象抛出 AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53702343/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com