2015-01-08 59 views
0

我遇到與MSVC和ICC的問題:如何使用__stdcall使用可變參數沒有編譯器破壞堆棧

我需要使用varadic參數與stdcall調用,但是編譯器會忽略它的varadic功能並破壞堆棧。

解決這個問題的簡單方法是將參數數目作爲參數之一,並在損壞之前將其偏移ESP,但在這種情況下,我不需要該函數上下文的參數個數如果可能的話,寧願避免它。

有人知道是否有辦法做到這一點?

+2

默認情況下你不行。當使用'stdcall'時,_callee_負責清理堆棧。由於_callee_不知道參數的數量或參數佔用多少堆棧空間,因此無法在不提供附加信息的情況下從邏輯上清理堆棧。你所要做的並不是一個好主意,任何試圖使它工作的嘗試可能會比努力付出更多的努力。這聽起來像是一個XY問題,你應該重新考慮你想要完成的事情。 –

+0

@CaptainObvlious這不是一個傳統的功能。真正最好的解決方案是做什麼即時通訊問(如果可能的話)。但請看我對約翰答案的回答;它更多地解釋了一點。 – Nowayz

回答

1

作爲每documentation

被叫清理堆棧,所以編譯器使得可變參數函數__cdecl

鑑於此,我不確定您期望如何繼續。如果stdcall要求被調用者清除堆棧,但在可變參數函數中,被調用者無法在編譯時知道堆棧上的內容,它將如何工作?你期望宏可以操縱呼叫幀嗎?我不認爲這就是微軟看到它的方式,所以你所要求的似乎不可能,至少不是使用微軟編譯器編寫C程序。

+0

在99%的情況下,嘗試這種做法很荒謬,我同意。不幸的是,在我的函數中,它確實清理了堆棧,但是我不能*清理堆棧,因爲它不是我的代碼。 – Nowayz

+2

@Nowayz不要害羞,100%的時間是荒謬的。 –

+0

@CaptainObvlious不是這次:)這個函數是代理調用到一個WINAPI(stdcall)中,它自己清理堆棧,然後將一個jmp返回到緩存的retn指針,因爲它必須從棧頂洗掉。這意味着堆棧每次都有100%的正確清理,但編譯器仍然試圖做到這一點。 – Nowayz