C 为什么在BSS和数据段中将不同大小的内存分配给integer?
请完成以下程序-C 为什么在BSS和数据段中将不同大小的内存分配给integer?,c,unix,memory,memory-management,C,Unix,Memory,Memory Management,请完成以下程序- #include <stdio.h> void main() { } 声明全局变量后- #include <stdio.h> int i; void main() { } 声明全局变量并用10初始化后- #include <stdio.h> int i=10; void main() { } 我的问题是,为什么全局变量“i”在存储在BSS时的内存大小为8字节,而在存储在数据段时的内存大小为4字节? 为什么在BSS和数据段中为整数
#include <stdio.h>
void main()
{
}
声明全局变量后-
#include <stdio.h>
int i;
void main()
{
}
声明全局变量并用10初始化后-
#include <stdio.h>
int i=10;
void main()
{
}
我的问题是,为什么全局变量“i”在存储在BSS时的内存大小为8字节,而在存储在数据段时的内存大小为4字节?
为什么在BSS和数据段中为整数分配内存会有差异
为什么全局变量“i”存储在BSS中时内存大小为8字节,而存储在数据段中时内存大小为4字节
首先,为什么数据段中有4个字节?
正如许多人已经回答过的那样,.data段包含任何预先初始化的全局或静态变量。一个整数的大小为4字节,当全局inti=10时,它反映在数据段大小中代码>在您的程序中
现在,为什么.bss段中有8个字节?
您之所以观察到这种行为,是因为GNU linkerGNU ld的默认链接器脚本。您可以获取有关链接器脚本的信息
链接时,GNU linker()使用默认的链接器脚本
默认链接器脚本指定.bss段的对齐方式
如果要查看默认链接器脚本,可以使用命令-
gcc -Wl,-verbose main.c
此gcc
命令的输出将包含以下语句:
using internal linker script:
==================================================
// The content between these two lines is the default linker script
==================================================
在默认链接器脚本中,您可以找到.bss
部分:
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
在这里,您可以看到=对齐(.!=0?64/8:1)代码>表示默认对齐方式为8字节
该方案:
#include <stdio.h>
int i;
void main()
{
}
[bss=24字节(16+8)]
GNU链接器提供了一个将自己的链接器脚本传递给它的设置,在这种情况下,它使用传递给它的脚本来构建目标,而不是默认的链接器脚本
要尝试此操作,可以将默认链接器脚本的内容复制到文件中,并使用此命令将链接器脚本传递到GNU ld
:
gcc -Xlinker -T my_linker_script main.c
因为您可以拥有自己的链接器脚本,所以您可以对其进行更改并查看行为的更改
在.bss
部分中,更改此=对齐(.!=0?64/8:1)代码>到=对齐(.!=0?32/8:1)代码>。这会将默认对齐方式从8字节更改为4字节。现在使用带有此更改的链接器脚本构建您的目标
输出为:
# size a.out
text data bss dec hex filename
1040 484 20 1544 608 a.out
在这里您可以看到,由于4字节对齐,bss的大小是20
字节(16+4)
希望这能回答您的问题。也许这是一个对齐要求。在我的机器(x86_64 Linux)上,.bss大小似乎是8的整数倍(向下),而.data部分则不是。现在,我需要添加两个未初始化的int以增加8,但是每个初始化的int会使.data部分增加4。有趣的问题。未初始化的变量位于bss
部分,该部分应该是一个虚拟部分,它只包含一个要保留的空间计数器,但按照二进制格式的要求在边界上对齐。声明初始化变量时,它的init值存储在数据段中,使32位int
的值增加4字节。这将最终改变文件图像中后面的bss
部分上的位置。如果对齐间距被计为bss
space,则该值将发生变化。由于所有这些都高度依赖于编译器,您应该说明您使用的编译器和版本以及编译器标志。@Frankie_C global和static默认初始化为0。绝对正确。。。
#include <stdio.h>
int i;
void main()
{
}
# size a.out
text data bss dec hex filename
1040 484 24 1548 60c a.out
gcc -Xlinker -T my_linker_script main.c
# size a.out
text data bss dec hex filename
1040 484 20 1544 608 a.out