C 进程的退出状态如何取决于它是否';它是静态构建的吗?

C 进程的退出状态如何取决于它是否';它是静态构建的吗?,c,gcc,static-linking,dynamic-linking,libc,C,Gcc,Static Linking,Dynamic Linking,Libc,现代制度: % pacman -Q glibc gcc glibc 2.16.0-4 gcc 4.7.1-6 % uname -sr Linux 3.5.4-1-ARCH 一个简单的程序: % < wtf.c void main(){} 一切看起来都很好: % file wtf? wtfd: ELF 64-bit LSB executable, x86-64, version 1 (SYSV

现代制度:

% pacman -Q glibc gcc
glibc 2.16.0-4
gcc 4.7.1-6
% uname -sr
Linux 3.5.4-1-ARCH
一个简单的程序:

% < wtf.c   
void main(){}
一切看起来都很好:

% file wtf?                                             
wtfd: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x4b421af13d6b3ccb6213b8580e4a7b072b6c7c3e, not stripped
wtfs: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=0x1f2a9beebc0025026b89a06525eec5623315c267, not stripped
有人能给我解释一下吗

% for n in $(seq 1 10); do ./wtfd; echo $?; done | xargs
0 0 0 0 0 0 0 0 0 0
% for n in $(seq 1 10); do ./wtfs; echo $?; done | xargs
128 240 48 128 128 32 64 224 160 48
当然,可以使用
intmain()
。并且
-Wmain
将发出警告(
返回类型“main”不是“int”


我只是想了解那里发生了什么。

这正是问题所在

没有“void main()”。总是有一个结果值,如果您不返回一个结果值,也不在程序中执行任何操作,那么返回值就是程序启动时适当寄存器中发生的值(或者具体地说,从启动代码调用main时发生的任何值)。这当然取决于程序在main之前做了什么,比如处理共享lib

编辑:要了解这是如何发生的,请尝试以下操作:

int foo(void)
{
    return 55;
}

void main(void)
{
    foo();
}

当然,不能保证,但是这个程序很有可能有55的退出代码,因为这是某个函数返回的最后一个值。想象一下那个电话发生在梅因之前。

进一步说明克里斯蒂安在说什么。即使您声明了
void main()
,您的进程仍将返回
eax
中以前的值(因为您使用的是linux x86 arch)

因此,现在它总是返回55 b/c,上面的代码显式初始化
eax

$ cc rval.c 
$ ./a.out 
$ echo $?
55

同样,这个例子只适用于当前主要的OSs,因为我假设调用约定。没有理由操作系统不能有不同的调用约定,返回值可以在其他地方(RAM、寄存器等)。

根据规范,
main
的返回值应该
int
。是的,当然。我不是说这是好代码。我不是在问如何修复它。我想问的是,根据我的链接方式,这种行为实际上是如何变化的。请再次阅读答案。特别是关于寄存器的部分。然后看看那些不必要的代码,看看实际发生了什么,你很可能会看到它们之间的区别。
objdump-s
中大约有139138行。我希望能有一个更简单的解释。你并不是在处理让我吃惊的部分:静态和动态是如何产生差异的。完成动态加载程序后,我希望调用
\u start
入口点。我想不出任何东西会使glibc的静态和动态构建有所不同。
void main() {
    asm("movl $55, %eax");
}
$ cc rval.c 
$ ./a.out 
$ echo $?
55