内存布局的“size”命令(文本、数据、bss)

问题描述 投票:0回答:1

我想用c语言中的“size”命令来理解内存存储段。我分别做了这些:


file1.c

#include <stdio.h>
int main(void) {
    return 0;
}
  • gcc -o size1 file1.c
  • size size1.exe
text    data     bss     dec     hex filename
7446    1404     244   12708    24b4 ./size1.exe

file2.c

#include <stdio.h>
int glb; /* Uninitialized variable stored in bss*/
int main(void) {
    return 0;
}
  • gcc -o size2 file2.c
  • size size2.exe
text    data     bss     dec     hex filename
7446    1404     244   12708    24b4 ./size2.exe

file2.c
的大小中,我预计
bss
段会增加,但没有改变。为什么会发生这种事?

添加了全局变量,但bss段没有增加


编辑:

* 使用目标文件而不是 .exe 解决了我的问题,但现在 .bss 增加了 16 而不是 4

问题演变为为什么.bss增加16而不是4?

c gcc memory memory-management
1个回答
0
投票

通常的原因是“对齐”。程序中可能存在需要对齐到一定字节数的倍数的对象,这可能需要插入填充(已分配但未使用的字节)。新添加的对象可能碰巧放置在原本用于填充的区域中,在这种情况下,它实际上不会增加该部分的整体大小。

作为一个简单的示例,假设您的原始程序在

.bss
部分中有两个对象(例如,由启动代码使用),一个需要 2 字节对齐的 2 字节对象
my_short
,以及一个 8 字节对象
my_long 
需要 8 字节对齐。链接器可能会碰巧将它们放置在内存中,如下所示:

0x0 - 0x1: my_short
0x2 - 0x7: (padding)
0x8 - 0xf: my_long

总共使用了16个字节,其中包括6个字节的填充。

现在添加一个新对象

glb
,4字节,需要4字节对齐。根据链接器处理其目标文件的顺序,它可以放置在
my_short
之后但在
my_long
之前。在这种情况下,内存映射可能如下所示:

0x0 - 0x1: my_short
0x2 - 0x3: (padding)
0x4 - 0x7: glb
0x8 - 0xf: my_long

总数仍然是 16 个字节,但现在只有 2 个字节的填充。

您可以使用

-Wl,-M
选项(这是一个带有逗号的选项,没有空格)为每个版本发出链接器映射,您应该能够看到它的发生。


在我的系统上,两个版本都有一个 8 字节的

.bss
部分。
ld
使用的链接器脚本(可以使用
-Wl,--verbose
打印)在
ALIGN
末尾包含一个
.bss
指令,因此
.bss
始终以 8 字节的倍数结束。 (脚本文件中有一条 FIXME 注释,表明其中一位程序员不确定他们为什么这样做,或者是否真的有必要。)

除了

glb
之外,
.bss
中只有 1 个字节(由启动代码使用),因此后面要么是 7 个字节的填充,要么是 3 个字节的填充,后跟
glb

© www.soinside.com 2019 - 2024. All rights reserved.