2013-04-10 84 views
3

我有一段代碼使用Delphi XE3編譯爲64位COM DLL。CopyMemory導致Win8上的訪問衝突

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; 

任何想法?謝謝。

+0

爲什麼u使用CopyMemory的,而不是標準的Pascal'Move'程序?或者,如果你不喜歡標準函數,那麼來自http://FastCode.sf.net的優化函數呢? – 2013-04-10 15:55:53

+2

@ Arioch'The 32位編譯器使用FastCode'Move',沒有64位FastCode'Move'。 – 2013-04-10 15:58:02

+2

我不能說Doctorlai,@Arioch,但*我更喜歡'CopyMemory',因爲我發現指針比無類型的引用參數更容易挖掘,並且我每天都以多種語言工作,所以擁有一個通用API是有幫助的。此外,由於API將所有內容直接轉發給內置函數,所以任何人都可以選擇。 – 2013-04-10 16:01:14

回答

7

此時:

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

您截斷一個64位指針爲32位。因此訪問衝突。相反,你需要

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

你的代碼是一樣破Win7上,但不知何故,你是不吉利的,只有不斷運行這個代碼與地址< 4GB的指針。

您應該運行一些自頂向下的內存分配測試來清除其他任何此類錯誤。

+0

謝謝。很大的幫助。是。我剛剛意識到這個愚蠢的錯誤。我將爲所有內存指針快速替換所有LongWord(x)到NativeUInt()。 – 2013-04-10 15:57:40

+0

留意我的建議並運行自上而下的分配測試。我相信你會發現更多的錯誤。 – 2013-04-10 15:58:37

+1

運行自上而下分配測試的具體情況如何? – 2013-04-10 16:04:05

4

David指出了你的問題的根源 - 你的指針類型轉換對於64位是錯誤的。一個更好的解決方案是使用指針運算來代替,讓編譯器處理指針大小爲您提供:

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

或者:

Move(
    (PByte(Self.FMemory) + Self.FPosition)^, 
    Buffer, 
    Result 
); 
+0

謝謝..所以這個PByte的東西將需要{$ POINTERMATH ON}的技巧,對吧?兩者都產生相同的代碼,對嗎? – 2013-04-10 21:19:41

+0

'POINTERMATH'只能通過'PByte'的RTL自動轉爲'ON',但需要手動轉換爲'ON'來處理任何其他需要使用指針運算的指針類型 – 2013-04-10 22:07:01

+0

我認爲,由於歷史事故,它也是'PAnsiChar'。 – 2013-04-10 22:43:07