簡體   English   中英

來自 PInvoke 的 x64 C 函數中的重疊內存地址

[英]Overlapping memory addresses in x64 C function from PInvoke

我們有一個 PInvoke 如下:

[DllImport(DllName, EntryPoint = "ExternalName", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ExternalFunction(IntPtr state, IntPtr inputData, int inputIndex, int inputLength, int tailLength);

C聲明如下:

void * __cdecl ExernalName(void* state, void* inputData, int32_t inputIndex, int32_t inputLength, int32_t tailLength);

當以 x86 運行 .NET 應用程序時,它工作正常。 然而,當在 x64 機器上的 AnyCPU 中運行時,函數參數的內存地址是關閉的。

例如,假設 state = 1、inputData = 2、inputIndex = 3 和 inputLength = 4。State 和 InputData 都是 void*,所以它們的長度應該是 8 個字節,而其余的應該是 4 個字節。

如果我在函數中設置斷點,則值為 state 2。假設 state 的內存地址確定為 0x00000008。

inputData 的內存地址返回為 0x0000000C,inputIndex 為 0x00000010,inputLength 為 0x00000014。

第一個問題,為什么inputData的內存地址在state之后4個字節,inputIndex在inputData之后4個字節? state 和 inputData 不應該每個是 8 個字節嗎?

第二個問題,如果我實際檢查值應該在哪里的內存地址,它們就在那里,但是 1 在哪里? 1 位於 0x00000000。

這怎么會發生? 我的錯誤假設是什么,我做錯了什么?

這是由 x64 模式下的調用約定引起的。 實際上,x64 中沒有 cdecl、stdcall 和 fastcall - 這些指令被忽略。

在 Windows 中,只有一種 x64 模式下的調用約定——Microsoft x64 調用約定。 在此約定中,如果每個參數的大小為 1、2、4 或 8 個字節,則前四個參數在寄存器中而不是通過堆棧傳遞。 同時,預留 32 字節用於調試。

這意味着獲取輸入參數的地址並直接從堆棧中讀取其值是沒有意義的。

嘗試在控制台上打印值,而不是在調試器中查看其值。 還要檢查可能強制使用 cdecl 而不是默認 x64 調用約定的編譯器選項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM