什么部分组成了可执行文件的大小?

我在尝试理解更大的问题时正在进行一些testing。 这是我的testing环境:

head.h

#define MAX_BUFSIZE 500 typedef struct { int head; int tail; int status; int active; void * dev[MAX_BUFSIZE]; char free[MAX_BUFSIZE]; int count; } msg_fifo_t; extern msg_fifo_t TxBufx[]; extern msg_fifo_t Rx_Buf[]; 

test.c

 #include <stdio.h> #include "head.h" //msg_fifo_t TxBufx[10]; // This is the important line int main(int argc, char * argv[]) { // This part isn't really important... printf("Hello Test\n"); return 0; } 

所以我使用这些文件,并运行三个testing,看看我有什么大小

testing#1(代码如上):

 > gcc -Os test.c > ls -al a.out -rwxrwxr-x 1 mike mike 7158 Jan 17 11:13 a.out > size a.out text data bss dec hex filename 1170 256 8 1434 59a a.out 

testing#2(取消注释“重要”行):

 > gcc -Os test.c > ls -al a.out -rwxrwxr-x 1 mike mike 7181 Jan 17 11:14 a.out > size a.out text data bss dec hex filename 1170 256 25208 26634 680a a.out 

testing#3(取消注释“重要”行并将TxBufx大小更改为100)

 > gcc -Os test.c > ls -al a.out -rwxrwxr-x 1 mike mike 7181 Jan 17 11:14 a.out > size a.out text data bss dec hex filename 1170 256 252008 253434 3ddfa a.out 

所以,现在我的问题:

  • 看起来,bss的大小几乎没有任何可执行文件的大小(从ls -al命令报告) – 任何人都可以向我解释为什么这是什么?

  • 编译器/链接器/平台是特定的特征吗?

  • 有没有比size更好的工具来了解这里发生的事情? (这意味着什么是真正的组成7181字节是我的可执行文件?)

由于bss段的内容, bss段中的数据量对可执行文件磁盘上的大小没有影响 – 这是程序中用于初始化为零的变量的部分。 由于这部分的内容是预先知道的(全零),所以实际存储在可执行文件中的唯一东西就是这个区域的大小

因此,随代码更改而变化的是data段的大小 – 表示静态初始化为非零值的变量以及code段的大小,表示与程序对应的已编译的可执行指令。

至于使用的工具,大多数Unix系统(它是GNU工具链的一部分)上的objdump(1)实用程序或MacOS X上的otool(1)实用程序都可用于获取有关哪些部分构成可执行文件的更多详细信息,每一个符号是什么。

bss是UN初始化的内存。 所以它唯一需要存储的是每个变量的起始地址和大小。 这就是为什么可执行文件的大小只有几个字节。

另外,即使初始化的内存( data段)在可执行映像中可能比初始化变量的总大小更小。
而不是在可执行文件中创建一个完整的初始化数据的图像,而是许多链接器插入如何初始化它的指令。 所以如果你已经做了char buffer[500] = {1,1,1,1,1,1,1,...}; ,可执行文件的data部分将在概念上看起来像

&TxBufx: fill with 500 1's

除了地址将是段的文字开始。 但是如果你添加一个全局的unsigned char bytecode[500] = {0x12, 0x34, 0x55, ... } ,那么你的数据段至少要增加500个字节,因为它不能使用任何快捷方式。