2

I am now reading chapter 6 of the book Expert C Programming and very curious about the size of the data segment.

I wrote 3 programs to see the difference of the data segment.

My platform is MacBook Pro, OS X 10.8 and I use the command clang xxx.c to compile the code.

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

Why are the all three sizes different from each other?

4

3 回答 3

4

除非你正在编写程序加载器,或者在嵌入式系统上工作,否则真的不需要关心不同的段。

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

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

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

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

如果有一个bss段,其中的数据通常会被程序加载器清零。关于bss段的另一个注意事项,它实际上不使用对象或可执行文件中的任何空间。由于它的数据是未初始化的,所以除了内存中的大小之外不需要存储任何东西。

于 2013-01-15T07:05:48.983 回答
1

文本部分是程序文本(或代码)所在的位置。因此,在您的三个示例中它会保持不变是有道理的。

首先,您没有全局变量,没有字符串文字等。因此数据大小为零。

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

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

许多可执行格式会将这些节大小调整为便于系统执行的内容。Intel x86 页面大小为 4KiB,这就是为什么我怀疑链接器将这些部分对齐到 4096。

于 2013-01-15T07:05:38.210 回答
0

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

在您的第三个示例中,数组是在函数的堆栈main()上创建的,即它最初存在,并且仅在进程进入后才被初始化main()这与“进程的完整生命周期”不同,因为有运行时支持之前运行的代码,以及在其之后运行的清理内容)。链接器在数据节中为某些东西保留空间(我不太确定是什么),其余部分(4096 减去保留项目的大小)是节被页面对齐的效果(即,以页面的倍数分配大小,在这种情况下为 4k)。main()

于 2013-01-15T07:04:57.507 回答