什么是Mac OS可执行文件的DATA段?

时间:2013-01-15 06:58:11

标签: c linker

我现在正在阅读 Expert C Programming 一书的第6章,对数据段的大小非常好奇。

我编写了3个程序来查看数据段的区别。

我的平台是MacBook Pro,OS X 10.8,我使用命令clang xxx.c来编译代码。

int main()
{
    int i, j;
    return 0;
}

__ TEXT 4096 __DATA 0


int arr[10000];
int main()
{
    int i, j;
    return 0;
}

__ TEXT 4096 __DATA 40960


int main()
{
    int i, j;
    int arr[10000];
    return 0;
}

__ TEXT 4096 __DATA 4096

为什么这三种尺寸都彼此不同?

3 个答案:

答案 0 :(得分:4)

除非您正在编写程序加载器或使用嵌入式系统,否则实际上无需关心不同的段。

然而,三个经典标准片段是:

  • text ,其中包含实际的可执行代码
  • 数据,其中包含初始化数据(例如初始化的全局变量)
  • bss ,其中包含未初始化的数据(例如未初始化的全局变量)

函数内部的变量在运行时被放置在堆栈中,因此没有特定的段。

这些段通常是平台页面大小的倍数,在i386和衍生物上是4096字节。因此,即使只需要一个字节,段大小也会向上舍入到4096字节。在第二个示例中,您有40000字节的数据,这会向上舍入到最接近的4096的倍数,即40960.

如果存在 bss 段,则其中的数据通常由程序加载器归零。关于 bss 段的另一个注意事项,它实际上不使用对象或可执行文件中的任何空格。由于其数据未初始化,因此无需在内存中存储任何大小的内容。

答案 1 :(得分:1)

文本部分是程序文本(或代码)所在的位置。所以在你的三个例子中它是恒定的是有意义的。

在第一个中,你没有全局变量,没有字符串文字等。所以数据大小为零。

在你的第二个例子中,你有一个~40 K的全局缓冲区,它位于数据部分(实际上可能是BSS,因为它未初始化,因此不会出现在可执行文件中。)

在第三个示例中,缓冲区位于main()的{​​{3}}。你没有添加任何全局数据,所以我不确定为什么它的数据大小非零。

许多可执行格式会将这些部分大小与方便系统执行的内容对齐。英特尔x86页面大小为4KiB,这就是我怀疑链接器将这些部分与4096对齐的原因。

答案 2 :(得分:0)

在第二个示例中,数组是静态初始化的,即它在进程的整个生命周期内都存在。链接器在数据部分中为10000个整数保留空间。

在第三个示例中,数组在main()函数的堆栈上创建,即它首先,并且仅初始化在进程进入main()之后(与&#34相同;进程的完整生命周期",因为在{{之前运行的运行时支持代码) 1}},以及运行后清理的东西)。链接器在数据部分保留空间(我不太清楚是什么),其余部分(4096减去保留项目的大小)是页面对齐的部分的效果(即,以页面的倍数分配)大小,在这种情况下为4k)。