【问题标题】:ByteArray from C++ Library crashes Delphi at DynArrayClearC++ 库中的 ByteArray 在 DynArrayClear 中使 Delphi 崩溃
【发布时间】:2011-12-31 00:18:59
【问题描述】:

我仍然遇到与此处提到的相同应用程序的问题 Delphi CopyMemory vs C++ memcpy

虽然我的原始问题得到了令人满意的答案,但我很难理解随后的崩溃......

我有一个使用网络库的 delphi 应用程序和一个使用相同网络库的服务器应用程序(存在于工作的某处)。网络库似乎可以正常工作是用 C++ 编写的(不是我写的)。该库为我处理所有通信,因此我只需向该库提供一个字节数组。我可以成功地向我的服务器发送和接收数据 - 并且数据在两个方向上都是正确的。

我在帮助程序中从服务器接收数据。程序正确运行到“结束”; (毫不夸张的说)。程序结束(我在这个阶段成功地通过了所有的通信,现在只关心 Delphi),调试器将我带到 _DynArrayClear - 我的应用程序崩溃的地方。从帮助中我读到“Delphi 编译器会在适当的时候自动插入对该函数的调用。”

如果有帮助,我会添加更多背景信息...网络库填充一个字节数组,该数组在内容结构中定义为 void *data(见下文)

struct content {
  void *data;
  int size;
}

我相信我需要做的就是在填充这些数据后在 Delphi 中执行 CopyMemory 操作...

谁能帮我理解我做错了什么?!

// should be: function THelper.ReceiveData: TBytes; - 
// but my crash happens with either a function or a procedure
procedure THelper.ReceiveData; 
var
  lMsg: Pointer;
  lSize: Integer;
  lData: TBytes;
  lRecvResult: Integer;
begin
  lMsg := nil;

  // Remote call to receive data returns an integer indicating success
  lRecvResult := lib_receive_data(lMsg, Integer(Flags));
  TUtils.CheckError(lRecvResult);

  SetLength(lData, 5);
  CopyMemory(@lData[0], lMsg, 5); // where 5 is the length of data to copy
end; // takes me into _DynArrayClear 



// The application crashes after exiting _DynArrayClear 
// For clarity @@noFinalize is entered at line 20795
// I get all the way to the 'end;' at line 20801 in System.pas
// 
// Then from _DynArrayClear I press F7 and immediately get access violation at 0xcdcdcdcd: read address of 0xcdcdcdcd and the following is the call stack...

:7789fada ntdll.NtQueryInformationProcess + 0x12
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll

【问题讨论】:

  • 我不肯定,但我认为您的问题是使用TBytes;你试过TByteArrayPByteArray 吗?
  • lData 动态数组在您的过程中是本地的。当它超出范围时,即退出过程时,它会自动销毁。我还不能弄清楚为什么你会得到一个例外。
  • 我已经尝试过 TByteArray 和 PByteArray... 同样的问题,这让我想知道它是否是被删除两次的 void *data 或根本没有?我疲惫的眼睛不知道这个问题的答案
  • 您的过程不会从 lMsg 指向的内容中释放任何内存。那东西没问题。您是否检查过 lMsgCopyMemory 之前是否为 nil ?您是否尝试过使用 try .. except 拥抱 CopyMemory?
  • 看起来堆栈坏了。检查 C 和 Delphi 代码中 lib_receive_data 声明的调用约定。

标签: c++ delphi memory bytearray


【解决方案1】:

lRecvResult := lib_receive_data(lMsg, Integer(Flags));

lib_receive_data() 的第一个参数实际声明为什么?您正在传递一个初始设置为nil 的本地Pointer 变量,所以我假设该参数是var,当lib_receive_data() 退出时,它被分配了一些有意义的内存地址? lib_receive_data() 实际输出了什么?

您的意思是content 结构,但我没有看到您在任何地方使用它。你声明了一个lSize 变量,但你也不使用它。 lib_receive_data() 的文档实际上是怎么说的?

SetLength(lData, 5); CopyMemory(@lData[0], lMsg, 5); // 其中 5 是要复制的数据长度

你确定lMsg 总是指向一个至少包含 5 个字节的缓冲区吗? lib_receive_data()的返回值代表什么?是字节数,还是只是状态码?

您在0xcdcdcdcd 之类的地址出现错误这一事实表明您可能会践踏TBytes 内存,这将导致_DynArrayClear()TBytes 被释放时崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多