【问题标题】:What sections make up the size of an executable?哪些部分构成了可执行文件的大小?
【发布时间】:2013-01-17 16:51:19
【问题描述】:

我在尝试理解larger problem 时进行了一个小测试。这是我的测试环境:

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;
 }

所以我使用了这些文件并运行了三个测试,看看我得到了什么大小 -

测试#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

测试#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

测试 #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 字节?)

【问题讨论】:

    标签: c linux gcc compilation size


    【解决方案1】:

    bss 段中的数据量对可执行文件的磁盘大小没有影响,因为bss 段是什么——这是您程序中用于变量的部分初始化为零。由于这部分的内容是预先知道的(全为零),所以真正存储在可执行文件中的只有这个区域的size

    所以的事情会随着代码的变化而改变,data 段的大小——表示静态初始化为非零值的变量,以及code 段的大小,代表你的程序对应的编译后的可执行指令。

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

    【讨论】:

    • The amount of data in the bss segment has no effect on the size on disk of your executable - 该声明是否得到保证?对于使用针对 uCLinux 的冷火工具链的不同编译器/链接器又如何呢? bss没有情况永远不会包含在可执行文件大小中吗?
    • 是的。 bss 根据定义只是初始化为零的数据。没有理由将此类数据写入文件。回想一下,这种 Unix 可执行文件模型是在 70 年代的小型计算机系统上开发的,这些系统实际上比今天的嵌入式系统更多资源受限。 :-)
    • @Mike - 无法保证所有系统上的所有编译器都会使用 bss 段。这只是一个广泛使用的实现细节。
    • 当然。但是另一个工具链(至少在类 Unix 系统上)不太可能将名称 bss 用于表示可执行文件中包含的实际段。 :-)
    【解决方案2】:

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

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

    &amp;TxBufx: fill with 500 1's

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

    【讨论】:

      猜你喜欢
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      • 2019-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      相关资源
      最近更新 更多