记 MSVC编译器对于函数调用风格的脑残行为(__cdecl\__stdcall)

众所周知,cdecl是父函数需要平衡栈,stdcall是子函数需要平衡栈,可是我近日发现stdcall函数指针调用,父函数也平衡栈了,是不是觉得非常奇怪?看如下代码:

typedef   void (*__cdecl CppCdeclTest_t)(int a,int b);
typedef   void (*__stdcall CppStdTest)(int a, int b);
int main()
{
   HMODULE dll=LoadLibrary(L"CallingConventionTest.dll");
   CppCdeclTest_t CppCdeclTest = (CppCdeclTest_t)GetProcAddress(dll, "CppCdeclTest");
   CppCdeclTest(5,2);
   CppStdTest CppStdlTest = (CppStdTest)GetProcAddress(dll, "?CppStdTest@@YGXXZ");
   CppStdlTest(5,2);
   getchar();
}
生成的汇编如下:
截取部分:
CppCdeclTest(5,2);
0074411A  mov         esi,esp  
0074411C  push        2  
0074411E  push        5  
00744120  call        dword ptr [CppCdeclTest]  
00744123  add         esp,8  ;由于CppCdeclTest是cdecl调用方式,由父函数恢复栈,所以这里add esp,8没什么问题
00744126  cmp         esi,esp  
00744128  call        __RTC_CheckEsp (0741212h)  

   CppStdTest CppStdlTest = (CppStdTest)GetProcAddress(dll, "?CppStdTest@@YGXXZ");
0074412D  mov         esi,esp  
0074412F  push        offset string "?CppStdTest@@YGXXZ" (0747BDCh)  
00744134  mov         eax,dword ptr [dll]  
00744137  push        eax  
00744138  call        dword ptr [__imp__GetProcAddress@8 (074B028h)]  
0074413E  cmp         esi,esp  
00744140  call        __RTC_CheckEsp (0741212h)  
00744145  mov         dword ptr [CppStdlTest],eax  
   CppStdlTest(5,2);
00744148  mov         esi,esp  
0074414A  push        2  
0074414C  push        5  
0074414E  call        dword ptr [CppStdlTest]  
00744151  add         esp,8  ;CppStdlTest是个stdcall的函数指针,按道理stdcall的话是由子函数把控栈指针,父函数不应该再生成这条汇编指令才对。
00744154  cmp         esi,esp  
00744156  call        __RTC_CheckEsp (0741212h)  

00744151  add         esp,8  ;CppStdlTest是个stdcall的函数指针,按道理stdcall的话是由子函数平衡栈指针,父函数不应该再生成这条汇编指令才对 ,为什么会生成呢?

解决方案:

typedef   void ( *__stdcall  CppStdTest)(int a, int b); ×
typedef   void (__stdcall * CppStdTest)(int a, int b);  √ 

改成下面的这个就好了。就不会生成那条指令了。

编译器的锅

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值