我发现了这个:
Because the stack is cleaned by the called function, the __stdcall calling convention creates smaller executables than __cdecl, in which the code for stack cleanup must be generated for each function call.
假设我有两个函数:
void __cdecl func1(int x)
{
//do some stuff using x
}
void __stdcall func2(int x, int y)
{
//do some stuff using x, y
}
在 main()
中:
int main()
{
func1(5);
func2(5, 6);
}
IMO,main()
负责清理对 func1(5)
和 func2
的调用堆栈将清理对 func2(5,6)
的调用堆栈,对吗?
四个问题:
1.对于在main()
中调用func1
,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);
}
2.main()
中调用func2
,清理堆栈是func2
自己的工作,所以我假设,在调用 func2
之前或之后,不会在 main()
中插入任何代码,对吗?
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
}
我想对吧?
4.最后,回到引用的话,为什么 __stdcall
比 __cdecl
产生更小的可执行文件?而且 linux 中没有 __stdcall
这样的东西,对吧?是不是linux elf总是比win下的exe大?
最佳答案
- 它只会在调用后插入代码,即重置堆栈指针,只要有调用参数。*
__stdcall
在调用点不生成清理代码,但是,应该注意编译器可以将多次__cdecl
调用的堆栈清理累积到一次清理中,或者它可以延迟清理以防止管道停顿。- 忽略此示例中的倒置顺序,不,它只会插入代码来清理
__cdecl
函数,函数参数的设置是不同的(不同的编译器生成/偏好不同的方法)。 __stdcall
更像是 Windows 的东西,参见 this .二进制文件的大小取决于对__cdecl
函数的调用次数,更多调用意味着更多清理代码,而__stdcall
只有 1 个清理代码实例。但是,您不会看到大小增加太多,因为每次调用最多只有几个字节。
*区分清理和设置调用参数很重要。
关于c++ - __cdecl 导致比 __stdcall 更大的可执行文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9173051/