C 函数指针使程序崩溃?

Sin*_*ame 1 c winapi pointers function

我正在尝试编写一个函数,该函数从我传递给它的结构指针中获取 MessageBoxA 的地址,然后使用该地址调用 MessageBoxA。问题是我尝试用这种方法调用 MessageBoxA 5 次,但我的程序总是在 3 次后崩溃,我不知道为什么。

void code(struct ShellD * s)
{

    s->pMsgBox(NULL,"s","s",MB_OK);

    s->pMsgBox(NULL,"s","s",MB_OK);

    s->pMsgBox(NULL,"s","s",MB_OK);

    s->pMsgBox(NULL,"s","s",MB_OK);

    s->pMsgBox(NULL,"s","s",MB_OK);
}

int main(int argc, char **argv)
{

struct ShellD SD;

SD.pMsgBox = GetProcAddress(LoadLibraryA("user32.dll"),"MessageBoxA");

code(&SD);

}
Run Code Online (Sandbox Code Playgroud)

Rup*_*Rup 5

pMsgBox 定义为 int (*pMsgBox)(HWND,LPCSTR,LPCSTR,UINT);

您已经WINAPI从 的声明中删除了MessageBoxA

int
WINAPI // <--
MessageBoxA(
    __in_opt HWND hWnd,
    __in_opt LPCSTR lpText,
    __in_opt LPCSTR lpCaption,
    __in UINT uType);
Run Code Online (Sandbox Code Playgroud)

pMsgBox 应该是这样的:

int (WINAPI *pMsgBox)(HWND,LPCSTR,LPCSTR,UINT)
Run Code Online (Sandbox Code Playgroud)

有什么不同?

  • Windows API 函数使用stdcall调用约定(也称为 Pascal 调用约定)。stdcall函数的特性之一是它们会清理传入的任何参数所使用的堆栈空间。

  • 相比之下,在默认的cdecl调用约定中,调用代码会为它传入的任何参数清理堆栈空间。

通过在 的声明中使用错误的调用约定,您pMsgBoxcode()函数和MessageBoxA()函数都在移动堆栈指针以删除传递的参数,并且在几次之后您可能已经将堆栈指针移出当前堆栈帧,然后被覆盖堆栈上的其他东西,例如返回函数指针。这可能是导致崩溃的原因。