__cdecl导致比__stdcall更大的可执行文件?

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.对于调用func1in 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.对于调用func2in 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更大?

Nec*_*lis 5

  1. 它只会在调用后插入代码,即重置堆栈指针,只要有调用参数.*
  2. __stdcall在调用站点没有生成清理代码,但是,应该注意编译器可以将多次__cdecl调用的堆栈清理累积到一次清理中,或者它可以延迟清理以防止管道停顿.
  3. 忽略这个例子中的反转顺序,不,它只会插入代码来清理__cdecl函数,设置函数参数是不同的(不同的编译器生成/偏好不同的方法).
  4. __stdcall更像是窗户,看到这个.二进制文件的大小取决于对__cdeclfuncs 的调用次数,更多的调用意味着更多的清理代码,其中__stdcall只有1个清理代码的单一实例.但是,您不应该看到大小增加,因为每次调用最多只有几个字节.

*区分清理和设置呼叫参数很重要.