在函数调用时,计算机用栈来维持函数调用的上下文信息,我们称之为栈帧。
Linux和windows下栈的大小都是预先确定的,大小为1M,这个大小是可以更改。
调用函数前,首先把主调函数下一指令的地址入栈,然后函数的参数入栈。
调用函数前有两个比较重要的问题要解决:
1、参数入栈的顺序?
2、谁来清理栈内存?函数调用约定则解决了这两个问题:
_cdecl C调用方式,是C语言缺省的调用方式
1、参数从右向左依次压入堆栈
2 、主调方开辟形参内存,被调用方自己释放栈内存
3、编译时函数名自动加前导下划线。
_stdcall windows标准的调用约定
1、 参数从右向左依次压入堆栈
2、调用方开辟形参内存,被调用方自己释放内存
3、编译时函数名自动加前导下划线,后面紧跟着一个@,其后紧跟着参数的尺寸
_fastcall 快速调用约定
1、参数从右向左依次压入堆栈
2、调用方开辟形参内存,但是把最左边的(也就是最后8字节的实参通过寄存器带到被调用函数里)
被调用方自己释放内存
3、编译时函数命名规则同stdcall
_thiscall thiscall调用约定意味着:
1、参数从右向左依次压入堆栈
2、参数个数不定的:由调用者清理堆栈,否则由函数自己清理堆栈。
3、thiscall 调用方式是唯一一种不能显示指定的修饰符因为它是c++类成员函数缺省的调用方式。
由于成员函数调用还有一个this指针,因此必须用这种特殊的调用方式。
对于参数个数固定的情况,它类似于stdcall,不定时则类似于cdecl。
_naked call参数入栈顺序是从左向右,比较复杂,已经很少用
如果定义的约定和使用的约定不一致,则将导致堆栈被破坏,导致严重问题,下面是两种常见的问题:函数原型声明和函数体定义不一致
DLL导入函数时声明了不同的函数约定
导致的结果是在调用函数的时候将栈帧破坏了。
本文详细介绍了不同平台下的函数调用约定,包括cdecl、stdcall、fastcall及thiscall等,并探讨了参数入栈顺序、栈内存清理责任归属以及调用约定不当可能导致的问题。
1万+

被折叠的 条评论
为什么被折叠?



