2012-07-01 33 views
0

我的問題是2010 MSVS C++編譯器是從另一個DLL編譯器然後試圖對準堆棧這種方式從一個函數調用在運行時解析(GetProcAddress的+的GetModuleHandle)返回後生成的方式代碼:MSVS 2010 C++編譯器和堆棧對齊問題?

CALL DWORD PTR DS:[2000367C]    ; apiresolvedinruntime.dll 
    ADD ESP,12        ; <- this is the stack alignment 

這當然覆蓋返回地址和我的程序崩潰,有人可以解釋爲什麼編譯器調整堆棧時,它真的不應該這樣做嗎?

+0

請發佈(a)函數在模塊中的聲明,(b)如何通過'GetProcAddress'獲取函數指針,以及(c)如何調用函數。 –

+3

聽起來像調用約定不匹配:__stdcall與__cdecl,也許。您是否正確地使用與您調用的函數相匹配的函數指針的類型來註釋函數指針的類型? – reuben

回答

4

您沒有使用正確的調用約定調用運行時加載的函數。調用約定指定了堆棧發生情況的默認處理。最有可能的是,使用__stdcall調用約定(這是Windows DLL使用的東西)來編譯DLL,它指定被調用函數應該清理堆棧,但調用代碼是使用函數指針聲明的,使用__cdecl調用約定(這是默認值)。在__cdecl之下,函數支持可變參數,所以調用者需要清理堆棧,因爲被調用的函數不知道傳遞了多少個參數。

您需要驗證DLL和調用代碼是否使用相同的調用約定進行編譯。

+0

FWIW,這個問題在x64上被屏蔽,因爲這兩個調用約定在Windows x64 ABI中是相同的。 – reuben

+0

@Reuben:這是因爲在amd64上有一個標準調用約定(相當於x86上的'__fastcall')。 x86從來沒有一個標準的調用約定。 ('__fastcall'在x64處理器上更有用,因爲有更多的寄存器可用) –

+0

是的,我知道:)我只是在這裏留下這些信息作爲問題的背景材料。 FWIW雖然在x86上是__fastcall的精神,但它並不完全等同於我的理解;堆棧對齊,可以裝入寄存器的參數數量,寄存器參數所需的溢出空間等等都顯得不同。 – reuben