Delphi 7到Delphi XE5

时间:2014-05-20 07:02:47

标签: delphi delphi-7 delphi-xe5

我正在将基于Indy TCP组件的服务器从Delphi 7移植到XE5,以实现64位支持。现在,在我完成所有移植并运行服务器后,它在测试环境中工作得很好。它工作得很好,直到用户数超过400.之后它开始创建访问冲突错误。有时打破错误会将我指向indy源文件,有时会指向CPU窗口。我无法确定生成错误的源代码区域。

虽然这种访问冲突错误意味着我正在访问一些尚未实例化的对象,但是为什么当较少用户在线并且整个代码与Delphi 7代码完全相同时,错误生成,则访问对象并以与在Delphi 7中相同的方式释放。

我在某处读到了与指针相关的东西应该使用NativeInt而不是Integer / Cardinal,现在在我处理传入数据的代码中,代码看起来像这样

procedure TMyContext.AddToPacketBuffer(Buffer: Pointer; Size: Integer);
var
  DestPtr: Pointer;
begin
  if PacketBufferPtr + Size<65536 then
  begin
    DestPtr := Pointer(Cardinal(FPacketBuffer)+Cardinal(PacketBufferPtr));
    Move(Buffer^,DestPtr^,Size);
    PacketBufferPtr := PacketBufferPtr + Size;
  end
  else
  begin
  end;
end;
  • FPacketBuffe r是在每个TMyContext类中声明的全局指针,PacketBufferPtr是在每个TMyContext类中声明的Integer变量

我应该在这里使用NativeInt而不是Cardinal吗?这可能是问题的根源吗?如果是,为什么当用户数低于400时没有创建错误,我使用本地环境中的所有函数进行测试,并且没有任何代码部分产生错误。

由于

1 个答案:

答案 0 :(得分:4)

64位代码必须了解的是指针是64位宽。与指针为32位宽的32位代码形成对比。现在,本机整数类型IntegerCardinal总是32位宽。显然,您无法在32位类型中容纳所有64位值。

你是正确的,这个代码在64位下被破坏了。将64位指针强制转换为32位整数可能会导致截断。如果地址适合您的32位类型,代码可能会起作用。如果您必须执行此类演员,则需要转为NativeIntNativeUInt。除了更改强制转换之外,您还需要声明任何包含NativeIntNativeUInt指针的变量。

当然,理想情况下,你应该努力避免这种演员阵容。你可以通过不使用Integer变量存储指针来做到这一点。将指针存储为指针,避免转换为整数,并且永远不会遇到指针截断错误。

尽管如此,PacketBufferPtr的名称非常具有误导性。它不是名称所暗示的指针。这是抵消。它应该命名为PacketBufferOffset。似乎有理由它永远不会超过high(Integer),所以也许Integer是一个合理的选择。但宣布它为NativeUInt永远不会有害。

因此,假设您将指针声明为PByte,将偏移量声明为NativeUInt,那么代码将按如下方式编写:

var
  FPacketBuffer: PByte;
  PacketBufferOffset: NativeUInt;
....    
procedure TMyContext.AddToPacketBuffer(Buffer: Pointer; Size: Integer);
var
  DestPtr: PByte;
begin
  if PacketBufferOffset + Size<65536 then
  begin
    DestPtr := FPacketBuffer + PacketBufferOffset;
    Move(Buffer^, DestPtr^, Size);
    inc(PacketBufferOffset, Size);
  end
  else
  begin
  end;
end;

现在代码没有强制转换。

我建议您启用自上而下的内存分配作为调试辅助工具。这将消除这种性质的更多错误。