了解 C 中数据 bss 段的大小命令
understanding size command for data bss segment in C
我从 size
命令中得到了意外的输出。
Afaik 初始化存储在 data
段中的全局和静态变量,未初始化并初始化为 0 global/static 存储在 bss
段中的变量。
printf("%d",sizeof(int));
给出 int
大小 4。但是,bss
和 data
段没有相应地增加到 4。
#include <stdio.h>
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2512 14848 3a00 memory-layout.exe
#include <stdio.h>
int g; //uninitialised global variable so, stored in bss segment
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2528 14864 3a10 memory-layout.exe
为什么 bss
增加了 16 (2528 - 2512) 而不是 4? (在上面的代码中)
#include <stdio.h>
int g=0; //initialised to 0 so, stored in bss segment
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2512 14848 3a00 memory-layout.exe
尽管使用了全局变量,bss
中没有增量。这是为什么?
#include <stdio.h>
int main()
{ static int g; //should be on bss segment
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.ex
text data bss dec hex filename
10044 2292 2512 14848 3a00 memory-layout.exe
尽管使用了静态变量,bss
段却没有增加,为什么?
我还有一个问题,dec
在这里代表什么?
首先要考虑的是内存对齐。可以填充变量和部分,使它们位于地址边界上。在第二个示例中,您看到比第一个增加了 16,这表明填充 16 字节边界(2512 / 16 = 157、2528 / 16 = 158)。这完全取决于实现。
就 C 而言,第二个示例与第三个示例不同,因为编译器无法知道 int g
是一个定义还是只是另一个文件中定义的整数的声明(它可以是任何价值)。它留下一个引用供链接器处理,这可能会导致填充差异。
在第三个示例中,g
被显式定义并设置为 0,因此编译器知道将其放入 BSS 部分。
可以用我的系统生成的程序集来证明这一点:
with int g
(在这种情况下没有定义 BSS 部分)
.comm g,4,4
这是链接器处理符号的指令,因为编译器无法完全确定如何处理它。
和int g = 0
.bss
.align 4
.type g, @object
.size g, 4
g:
.zero 4
在这里,编译器确切地知道要做什么,因此为符号定义了一个 BSS 部分。
在我的例子中,链接器以相同的方式解决这些问题。两者都放在相同地址的 BSS 部分,因此 BSS 大小没有差异。您可以使用 nm
.
等实用程序检查布局
nm -n file2 file3 | grep g$
000000000060103c B g
000000000060103c B g
即在此系统上 g
位于同一地址。或者,使用调试器:
(gdb) info symbol 0x60103c
g in section .bss of /tmp/file2
另请注意,在最后一个示例中,可以优化变量,因为它具有内部链接。
至于dec
,它只是小数部分的总和。
这是来自 linux 上的 gcc:
No Variable
text data bss dec hex filename
915 248 8 1171 493 none.out
Uninitialized Global
text data bss dec hex filename
915 248 12 1175 497 u_g.out
Initialized Global to 123
text data bss dec hex filename
915 252 8 1175 497 i_g.out
Initialized Local to 124
text data bss dec hex filename
915 252 8 1175 497 i_l.out
Initialized Global to 0
text data bss dec hex filename
915 248 12 1175 497 i_g_0.out
Initialized Local to 0
text data bss dec hex filename
915 248 12 1175 497 i_l_0.out
这是来自 Windows 上的 mingw64:
No Variable
text data bss dec hex filename
3173 1976 448 5597 15dd none.out
Uninitialized Global
text data bss dec hex filename
3173 1976 464 5613 15ed u_g.out
Initialized Global to 123
text data bss dec hex filename
3173 1976 448 5597 15dd i_g.out
Initialized Local to 124
text data bss dec hex filename
3173 1976 448 5597 15dd i_l.out
Initialized Global to 0
text data bss dec hex filename
3173 1976 480 5629 15fd i_g_0.out
Initialized Local to 0
text data bss dec hex filename
3173 1976 480 5629 15fd i_l_0.out
所以虽然我没有这个问题的最终答案(不适合发表评论),但结果让我怀疑 Windows and/or MinGW 的可执行文件格式(即不是 gcc)。
BSS 仅包含未显式初始化的静态和全局值。即使您将其显式初始化为与未显式初始化时相同的值,显式初始化的事实也意味着它不属于 bss。
我从 size
命令中得到了意外的输出。
Afaik 初始化存储在 data
段中的全局和静态变量,未初始化并初始化为 0 global/static 存储在 bss
段中的变量。
printf("%d",sizeof(int));
给出 int
大小 4。但是,bss
和 data
段没有相应地增加到 4。
#include <stdio.h>
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2512 14848 3a00 memory-layout.exe
#include <stdio.h>
int g; //uninitialised global variable so, stored in bss segment
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2528 14864 3a10 memory-layout.exe
为什么 bss
增加了 16 (2528 - 2512) 而不是 4? (在上面的代码中)
#include <stdio.h>
int g=0; //initialised to 0 so, stored in bss segment
int main()
{
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
text data bss dec hex filename
10044 2292 2512 14848 3a00 memory-layout.exe
尽管使用了全局变量,bss
中没有增量。这是为什么?
#include <stdio.h>
int main()
{ static int g; //should be on bss segment
return 0;
}
C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.ex
text data bss dec hex filename
10044 2292 2512 14848 3a00 memory-layout.exe
尽管使用了静态变量,bss
段却没有增加,为什么?
我还有一个问题,dec
在这里代表什么?
首先要考虑的是内存对齐。可以填充变量和部分,使它们位于地址边界上。在第二个示例中,您看到比第一个增加了 16,这表明填充 16 字节边界(2512 / 16 = 157、2528 / 16 = 158)。这完全取决于实现。
就 C 而言,第二个示例与第三个示例不同,因为编译器无法知道 int g
是一个定义还是只是另一个文件中定义的整数的声明(它可以是任何价值)。它留下一个引用供链接器处理,这可能会导致填充差异。
在第三个示例中,g
被显式定义并设置为 0,因此编译器知道将其放入 BSS 部分。
可以用我的系统生成的程序集来证明这一点:
with int g
(在这种情况下没有定义 BSS 部分)
.comm g,4,4
这是链接器处理符号的指令,因为编译器无法完全确定如何处理它。
和int g = 0
.bss
.align 4
.type g, @object
.size g, 4
g:
.zero 4
在这里,编译器确切地知道要做什么,因此为符号定义了一个 BSS 部分。
在我的例子中,链接器以相同的方式解决这些问题。两者都放在相同地址的 BSS 部分,因此 BSS 大小没有差异。您可以使用 nm
.
nm -n file2 file3 | grep g$
000000000060103c B g
000000000060103c B g
即在此系统上 g
位于同一地址。或者,使用调试器:
(gdb) info symbol 0x60103c
g in section .bss of /tmp/file2
另请注意,在最后一个示例中,可以优化变量,因为它具有内部链接。
至于dec
,它只是小数部分的总和。
这是来自 linux 上的 gcc:
No Variable
text data bss dec hex filename
915 248 8 1171 493 none.out
Uninitialized Global
text data bss dec hex filename
915 248 12 1175 497 u_g.out
Initialized Global to 123
text data bss dec hex filename
915 252 8 1175 497 i_g.out
Initialized Local to 124
text data bss dec hex filename
915 252 8 1175 497 i_l.out
Initialized Global to 0
text data bss dec hex filename
915 248 12 1175 497 i_g_0.out
Initialized Local to 0
text data bss dec hex filename
915 248 12 1175 497 i_l_0.out
这是来自 Windows 上的 mingw64:
No Variable
text data bss dec hex filename
3173 1976 448 5597 15dd none.out
Uninitialized Global
text data bss dec hex filename
3173 1976 464 5613 15ed u_g.out
Initialized Global to 123
text data bss dec hex filename
3173 1976 448 5597 15dd i_g.out
Initialized Local to 124
text data bss dec hex filename
3173 1976 448 5597 15dd i_l.out
Initialized Global to 0
text data bss dec hex filename
3173 1976 480 5629 15fd i_g_0.out
Initialized Local to 0
text data bss dec hex filename
3173 1976 480 5629 15fd i_l_0.out
所以虽然我没有这个问题的最终答案(不适合发表评论),但结果让我怀疑 Windows and/or MinGW 的可执行文件格式(即不是 gcc)。
BSS 仅包含未显式初始化的静态和全局值。即使您将其显式初始化为与未显式初始化时相同的值,显式初始化的事实也意味着它不属于 bss。