__cdecl比__stdcall产生更大的可执行文件? [英] __cdecl results in larger executable than __stdcall?
问题描述
我发现了这一点:
由于堆栈已被调用函数清除,因此__stdcall
调用约定会创建可执行文件,其中必须为每个函数调用生成
堆栈清理代码。
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.
假设我有2个函数:
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)
的调用的堆栈,对吗?
IMO, it is main()
's responsibility to clean up the stack of the call to func1(5)
, and func2
will clean up the stack of the call to func2(5,6)
, right?
四个问题:
1。用于调用 main()中的
,清理堆栈是 func1
主要
的责任,因此编译器将在之前和之后插入一些代码(清理堆栈的代码)。调用 func
?像这样:
1.For the call to func1
in main()
, it's main
's responsibility to clean up the stack, so will compiler insert some code (code to clean up the stack) before and after the call to func
? Like this:
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。用于调用 func2 $
main()
中的c $ c>,它是 func2
自己的工作,它用来清理堆栈,所以我想,在调用 func2
之前或之后,不会在 main()
中插入任何代码,对吗?
2.For the call to func2
in main()
, it's func2
's own job to clean up the stack, so I presume, no code will be inserted in main()
before or after the call to func2
, right?
3。因为 func2
是 __ stdcall
,所以我想,编译器会自动插入代码(清理堆栈),如下所示:
3.Because func2
is __stdcall
, so I presume, compiler will automatically insert code (to clean up the stack) like this:
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
这样的东西,对吗?
4.Finally, back to the quoted words, why __stdcall
results in smaller executable than __cdecl
? And there is no such a thing as __stdcall
in linux, right? Does it means linux elf will be always larger than exe in win?
推荐答案
- 这只会使Windows elf在win中总是比exe大吗?只要在调用参数之后的位置,在调用之后插入代码即可重置堆栈指针。*
-
__ stdcall
不会生成任何代码但是,应该注意,编译器可以将多个__ cdecl
调用中的堆栈清理累积到一个清理中,或者它可以延迟清理以防止管道停顿 - 在此示例中,忽略倒序,不,它只会插入代码来清理
__ cdecl
函数,设置函数参数是不同的(不同的编译器生成/更喜欢使用不同的方法)。 -
__ stdcall
更多的是Windows,请参见此。二进制文件的大小取决于对__ cdecl
函数的调用次数,更多的调用意味着更多的清理代码,其中__ stdcall
只有1个清除代码的单数实例。但是,您不应看到大小增加太多,因为每次调用最多只有几个字节。
- It'll only insert code after the call, which is to reset the stack pointer, so long as there where call arguments.*
__stdcall
generates no cleanup code at the call site, however, it should be noted that compilers can accrue stack cleanup from multiple__cdecl
calls into one cleanup, or it can delay the cleanup to prevent pipeline stalls.- Ignoring the inverted order in this example, no, it'll only insert code to cleanup the
__cdecl
function, setting up of function arguments is something different (different compilers generate/prefer different methods). __stdcall
was more a windows thing, see this. the size of the binary depends on the number of calls to the__cdecl
funcs, more calls means more clean up code, where as__stdcall
has only 1 singular instance of cleanup code. however, you shouldn't see that much size increase, as at most you have a few bytes per call.
*区分清理和设置调用参数。
*Its important to distinguish between cleanup and setting up call parameters.
这篇关于__cdecl比__stdcall产生更大的可执行文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!