【发布时间】:2013-11-21 07:19:41
【问题描述】:
来自Wikipedia:
此段的大小由程序员在程序编译或组装之前放置在那里的值确定,并且在运行时不会改变
那么究竟是谁决定了分段的大小?操作系统? 另外,什么时候计算? “在程序编译或组装之前”是否意味着它是在预处理阶段完成的?
【问题讨论】:
来自Wikipedia:
此段的大小由程序员在程序编译或组装之前放置在那里的值确定,并且在运行时不会改变
那么究竟是谁决定了分段的大小?操作系统? 另外,什么时候计算? “在程序编译或组装之前”是否意味着它是在预处理阶段完成的?
【问题讨论】:
您引用的维基百科文本是错误的或具有误导性。在汇编或编译之前不存在数据段。
数据段的构建方式如下。
在汇编中,程序员可以显式声明一个数据段并定义要放置在那里的值。当程序员使用某些功能时,一些汇编器还提供自动将数据添加到数据段的功能。例如,汇编线ldr r7, =345 可能会要求汇编器将 345 放入数据段,并在ldr 指令中填写其地址。
在高级语言中,编译器会在处理代码时构建所需的数据。这可以包括程序员直接编写的常量(例如,x = 345; 中的345 或在将高级代码转换为汇编的过程中创建的值。(例如,如果您编写了i = 35; y = x[i*3+7];,编译器可能会计算下标为 112 并将其存储在数据部分中)。
链接器将来自它处理的目标模块的数据段组合成一个数据段。大小只是组合数据的大小。 (某些数据段,例如 FORTRAN 公共段,可能是共享的,因此来自多个对象模块的数据是重叠的,而不是串联的。)
动态加载库时,它们的数据段不能在链接时合并,必须由加载器单独管理。所以一个正在执行的程序可能有多个数据段。
【讨论】:
对于传统的编译语言,答案大致是链接器。
发生的情况是每个目标文件都包含有关各个段的大小(和对齐等)的信息。当链接器将目标文件拼接在一起形成可执行文件时,它将以尊重对齐的方式聚合匹配的段。因此,部件的顺序以及最终段的潜在大小取决于链接器。
如果需要添加填充以保持对齐,则段的大小可能会发生变化。
请注意,解释或 JIT 编译的程序实际上没有段。
【讨论】:
“编译程序之前..”部分必须指应存在哪些变量和/或常量。
数据段/段的大小由链接器计算 - 编译/组装过程的一部分,负责实际构建输出文件,包括记录此类信息的标头。
大小计算又基于参与对象模块的数据部分包含的内容。
【讨论】: