我现在正在阅读 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
为什么这三种尺寸都彼此不同?
答案 0 :(得分:4)
除非您正在编写程序加载器或使用嵌入式系统,否则实际上无需关心不同的段。
然而,三个经典标准片段是:
函数内部的变量在运行时被放置在堆栈中,因此没有特定的段。
这些段通常是平台页面大小的倍数,在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)。