我收到了一些意外的行爲,這可能意味着我不完全理解編譯器在做什麼。請看下面的做作程序:從程序集調用C++函數,使用struct參數
#include <stdio.h>
#pragma pack(push, 1)
struct A {
unsigned short a;
unsigned short b;
explicit A() {
printf("construct\n");
}
~A() {
printf("destruct\n");
}
};
#pragma pack(pop)
static_assert(sizeof(A) == 4, "sizeof(A) != 4");
A __stdcall f(int p1, A p2, int p3, int p4) {
printf("%08X %08X %08X %08X\n", p1, p2, p3, p4);
return p2;
}
int main() {
__asm {
push 4
push 3
push 2
push 1
call f
}
return 0;
}
上述程序會崩潰,但如果我從struct A
去除A()
和~A()
的定義也不會。這個問題與編譯器認爲參數在堆棧中的位置有關,構造函數定義它認爲它們比它們的位置多4個字節。如果我刪除構造函數的輸出我得到的是這樣的:
00000001 00000002 00000003 00000004
這是我所期待的,但與構造函數定義我得到
00000002 00000003 00000004 00000000
這顯然不是我所期待的。運行前者時,函數返回RETN 0x10
,後者返回RETN 0x14
,因此它看起來應該有另一個參數(爲什麼?)。我注意到,如果我將f
更改爲void
函數,它將按預期工作。那麼,有人可以向我解釋發生了什麼,爲什麼?我已關閉所有優化。
'p2'屬於'A'類型。然而,你正在傳遞一個int。我很驚訝,它可以工作,因爲這是相當不明確的。你確定這是正確的代碼嗎? – Adrian
@Adrian'A'與int的大小相同,並且沒有虛函數,所以我不明白爲什麼它不起作用 – user1520427
當A是非POD時,將會出現意想不到的行爲。如果你真的想這樣做,請反彙編編譯器做什麼來查看真正發生的事情。 – Adrian