3

我有一段代码使用 Delphi XE3 编译成 64 位 COM DLL。

function TRPMFileReadStream.Read(var Buffer; const Count: Longint): Longint;
begin
  if ((Self.FPosition >= 0) and (Count > 0)) then
  begin
    Result := Self.FSize - Self.FPosition;
    if ((Result > 0) and (Result >= Count)) then
    begin
      if (Result > Count) then
      begin
        Result := Count;
      end;
      CopyMemory(
        Pointer(@Buffer),
        Pointer(LongWord(Self.FMemory) + Self.FPosition),
        Result
      );
      Inc(Self.FPosition, Result);
      Exit;
    end;
  end;
  Result := 0;
end;

在 Win7-64bit 上,上述工作正常。但是在 Win8-64bit 上,相同的 DLL 文件会在 CopyMemory 上引发访问冲突。CopyMemory 在 WinAPI.windows 单元中实现。

就像这样。

procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: NativeUInt);
begin
  Move(Source^, Destination^, Length);
end;

有任何想法吗?谢谢。

4

2 回答 2

7

在此刻:

Pointer(LongWord(Self.FMemory) + Self.FPosition)

您将 64 位指针截断为 32 位。因此访问冲突。相反,您需要

Pointer(NativeUInt(Self.FMemory) + Self.FPosition)

您的代码在 Win7 上同样损坏,但不知何故,您很不幸,只使用地址 < 4GB 的指针运行此代码。

您应该运行一些自上而下的内存分配测试以清除任何其他此类错误。

于 2013-04-10T15:52:35.557 回答
4

大卫指出了你问题的根源——你的指针类型转换对于 64 位是错误的。更好的解决方案是使用指针算法,让编译器为您处理指针大小:

CopyMemory(
  @Buffer,
  PByte(Self.FMemory) + Self.FPosition,
  Result
);

或者:

Move(
  (PByte(Self.FMemory) + Self.FPosition)^,
  Buffer,
  Result
);
于 2013-04-10T19:39:40.713 回答