我正在尝试理解.bss内存分配和取消分配背后的逻辑
我有几个案例,我试图理解相同的。
我的结论是,如果我在代码的全局范围内声明任何变量,它将以8字节的块递增,因为我的链接器脚本具有8字节的对齐
但当我在同一作用域中定义变量时,它会从.bss中释放内存
但我不明白的是,取消拨款背后的逻辑计算究竟是甚么?
情况1:
# include <stdio.h>
int a;
int b;
int main(void){
return 0;
}
此代码片段为不同的段生成以下大小
text data bss dec hex filename
1418 544 16 1978 7ba a.out
如果我初始化一个int变量
情况2:
# include <stdio.h>
int a = 1;
int b;
int main(void){
return 0;
}
这将提供以下大小表
text data bss dec hex filename
1418 548 12 1978 7ba a.out
现在如果我在int变量之前初始化一个字符
情况3:
# include <stdio.h>
char a = 1;
int b;
int main(void){
return 0;
}
它显示
text data bss dec hex filename
1418 545 12 1978 7ba a.out
这是nm-n输出,具体用于情况3
0000000000004000 D __data_start
0000000000004000 W data_start
0000000000004008 D __dso_handle
0000000000004010 D a
0000000000004011 B __bss_start
0000000000004011 D _edata
0000000000004014 b completed.8060
0000000000004018 D __TMC_END__
0000000000004018 B b
0000000000004020 B _end
如果我初始化一个int变量
情况4:
# include <stdio.h>
int a = 1;
char b;
int main(void){
return 0;
}
它显示
text data bss dec hex filename
1418 548 4 1978 7ba a.out
如果我初始化一个int变量
情况5:
# include <stdio.h>
char a = 1;
char b;
int main(void){
return 0;
}
它显示
text data bss dec hex filename
1418 545 7 1978 7ba a.out
有人能帮我理解一下吗?
1条答案
按热度按时间bvn4nwqk1#
给定类型的符号有链接器必须荣誉的自然对齐方式(例如
int
必须是4字节对齐)。在给定的节(例如.bss
)中,链接器有一定的余地来重新排序符号,这样给定符号的对齐方式就不会导致过多的填充。如果我们有:如果不进行重新排序,加载Map将如下所示:
并且,区段长度将为8。
重新排序:
并且,区段长度将为5
请注意,区段的大小是向上 * 对齐 * 到某个倍数(通常为8字节)。因此,例如,如果区段只有1字节的数据,则区段大小将报告为8。
但是,也有例外。
更清楚地了解这一点的方法之一是简化数据:
1.我们可以省略任何库或启动代码以减少可执行文件的大小。
1.我们可以使用相对于 * 第一个 * 数据段开始的地址(例如
.data
的开始)1.将所有案例的结果合并到一个表中
我已经创建了一个[perl]脚本来完成这个任务,它包含了您的原始测试用例和一些附加的测试用例。
特别值得注意的是案例6 ...
下面是脚本的输出。最后的表格[和讨论]在下面的FINAL部分。
案例1:
资料来源:
命令:
nm -n xfile
命令:
size xfile
案例2:
资料来源:
命令:
nm -n xfile
命令:
size xfile
案例3:
资料来源:
命令:
nm -n xfile
命令:
size xfile
案例4:
资料来源:
命令:
nm -n xfile
命令:
size xfile
案例5:
资料来源:
命令:
nm -n xfile
命令:
size xfile
型
案例6:
资料来源:
命令:
nm -n xfile
命令:
size xfile
存储器
最终版本:
请注意,在案例6中,
.data
的长度为5。而且,.bss
的起始地址[也]为5。但是,实际 * 使用 * 的最低.bss
地址为8(对于b
)下面是脚本源代码: