Alc*_*ott 4 c c++ compiler-construction calling-convention
我找到了这个:
由于堆栈由被调用函数清理,因此__stdcall调用约定创建比__cdecl 更小的可执行文件,其中必须为每个函数调用生成堆栈清理的代码.
假设我有两个功能:
void __cdecl func1(int x)
{
//do some stuff using x
}
void __stdcall func2(int x, int y)
{
//do some stuff using x, y
}
Run Code Online (Sandbox Code Playgroud)
在这里main()
:
int main()
{
func1(5);
func2(5, 6);
}
Run Code Online (Sandbox Code Playgroud)
IMO,有main()
责任清理堆栈的呼叫func1(5)
,并func2
清理堆栈的呼叫func2(5,6)
,对吗?
四个问题:
1.对于调用func1
in main()
,main
清理堆栈是有责任的,所以编译器会在调用之前和之后插入一些代码(清理堆栈的代码)func
吗?像这样:
int main()
{
before_call_to_cdecl_func(); //compiler generated code for stack-clean-up of cdecl-func-call
func1(5);
after_call_to_cdecl_func(); //compiler generated code for stack-clean-up of cdecl-func-call
func2(5, 6);
}
Run Code Online (Sandbox Code Playgroud)
2.对于调用func2
in main()
,func2
清理堆栈是自己的工作,所以我认为,main()
在调用之前或之后都不会插入代码func2
,对吧?
3.由于func2
是__stdcall
,所以我想,编译器将自动插入代码(以清理堆栈)所示:
void __stdcall func1(int x, int y)
{
before_call_to_stdcall_func(); //compiler generated code for stack-clean-up of stdcall-func-call
//do some stuff using x, y
after_call_to_cdecl_func(); //compiler generated code for stack-clean-up of stdcall-func-call
}
Run Code Online (Sandbox Code Playgroud)
我猜对了吗?
4.最后,回到引用的话,为什么__stdcall
结果会比较小的可执行文件__cdecl
?__stdcall
在linux中没有这样的东西,对吧?这是否意味着linux elf在win中总是比exe更大?
__stdcall
在调用站点没有生成清理代码,但是,应该注意编译器可以将多次__cdecl
调用的堆栈清理累积到一次清理中,或者它可以延迟清理以防止管道停顿.__cdecl
函数,设置函数参数是不同的(不同的编译器生成/偏好不同的方法).__stdcall
更像是窗户,看到这个.二进制文件的大小取决于对__cdecl
funcs 的调用次数,更多的调用意味着更多的清理代码,其中__stdcall
只有1个清理代码的单一实例.但是,您不应该看到大小增加,因为每次调用最多只有几个字节.*区分清理和设置呼叫参数很重要.