我正在将基于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类中声明的全局Pointer,并且PacketBufferPtr
是在每个TMyContext类中声明的Integer变量我应该在这里使用NativeInt而不是Cardinal吗?这可能是问题的根源吗?如果是的话,当用户数低于400时为什么不产生错误,所以我在本地环境中使用所有功能进行了测试,并且没有任何代码部分会产生错误。
谢谢
关于64位代码,您必须了解的是指针为64位宽。与指针为32位宽的32位代码相反。现在,原生整数类型Integer
和Cardinal
总是32位宽。显然,您不能将所有64位值都适合32位类型。
您是正确的,该代码是64位以下的。将64位指针强制转换为32位整数可能会导致截断。如果地址适合您的32位类型,则该代码可能会起作用。如果必须执行此类转换,则需要转换为NativeInt
或NativeUInt
。并且除了更改强制类型转换外,您还需要声明任何将指针保存为NativeInt
或的变量NativeUInt
。
当然,理想情况下,您应该努力完全避免此类转换。您可以通过不使用Integer
变量at来存储指针来实现。将指针存储为指针,避免转换为整数,并且永远不会遭受指针截断错误。
就是说,的名称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;
现在,代码中没有强制转换。
我建议您启用自上而下的内存分配作为调试辅助。这将清除更多此类错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句