1. a.out
有使用过linux的都知道,在linux下编译链接程序,如果不加-o参数,所有的输出文件都默认使用同一个名字a.out。a.out是"assembler output"的缩写格式,代表汇编程序输出。在较早版本的类unix系统中,a.out是一种输出格式,用于可执行文件,但到PDP-11之后,人们为其编写了链接器,程序的创建是先编译然后链接输出保存到a.out中,这时a.out其实已经是链接输出了,但输出的可执行文件仍然延续这个命名习惯。因为构建a.out的复杂性,a.out格式被现在普遍使用的ELF(Executable and Linking Format)格式所替代,但输出文件名仍旧是a.out,现在我们看到的a.out只是一个可执行文件,而不再是文件格式。
2.段
不管是a.out格式、ELF格式还是COFF格式,所有这些不同格式具有共同的概念,那就是段(segments),在UNIX中,段表示一个二进制文件相关的内容块。一个可执行文件有三个段:文本段(代码段)、数据段、bss段(Block Started by Symbol),可用size的命令查看段的大小。
text指的是程序指令
data指的是所有的经过初始化后的全局变量和静态变量
bss段则是未经初始化的全局变量和静态变量,但是bss段不增加目标文件的大小,一般只是记录bss段的大小。
例子1#f1.c:
int main() { printf("hello word! "); return 0; }
结果:
$ gcc -o f1 f1.c $ ls -l f1 -rwxrwxr-x. 1 xjx xjx 4680 3月 24 11:45 f1 $ size f1 text data bss filename 1035 252 8 f1
分析:目标文件4680字节,text段1035字节、data段252字节、bss段8字节大小
说明:
(1) bss段不保存在目标文件中,除了记录bss段在运行时的大小
例子2#f2.c:
#include<stdio.h> int a[1000];//全局数组 int main() { printf("hello word! "); return 0; }
结果:
$ gcc -o f2 f2.c $ ls -l f2 -rwxrwxr-x. 1 xjx xjx 4698 3月 24 12:01 f2 $ size f2 text data bss filename 1035 252 4032 f2
分析:
目标文件4698字节,相对f1未明显增加,text段1035字节、data段252字节、bss段4032字节大小。可以推出未初始化的全局变量数组a,存在于bss段,且不增加目标文件的大小
(2) data段保存在目标文件中
结果:#include<stdio.h> int a[1000]={1};//初始化全局变量 int main() { printf("hello word! "); return 0; }
分析:$ gcc -o f3 f3.c $ ls -l f3 -rwxrwxr-x. 1 xjx xjx 8734 3月 24 12:07 f3 $ size f3 text data bss filename 1035 4280 8 f3
目标文件8734字节,相对f2文件明显变大;text段1035字节、data段4280字节,明显变大;bss段8字节大小。可以推出初始化后使得数组从bss段转换到data段,从而使目标文件变大。
(3)局部变量不在可执行文件中
例子4#f4.c:
#include<stdio.h> int a[1000]={1}; int main() { int b[1000],c[1000]={1};//局部变量 printf("hello word! "); return 0; }
结果:
分析:$ gcc -o f4 f4.c $ ls -l f4 -rwxrwxr-x. 1 xjx xjx 8798 3月 24 12:14 f4 $ size f4 text data bss filename 1083 4280 8 f4
目标文件8798字节,相对f3文件无明显变化;text段1083字节、data段4280字节、bss段8字节大小。可以推出局部变量不进入目标文件,运行时创建。