This question already has an answer here:
Why the int type takes up 8 bytes in BSS section but 4 bytes in DATA section

(1 个回答)


3年前关闭。




请通过以下程序 -
#include <stdio.h>
void main()
{
}

为每个段分配的内存如下(在 Unix 上使用 size 命令)-
   text    data     bss     dec     hex filename
   1040     484      16    1540     604 try

声明全局变量后-
#include <stdio.h>
int i;

void main()
{
}

为每个段分配的内存如下(在 Unix 上使用 size 命令)
此处变量“i”已在 BSS 中接收到内存(以前为 16,现在为 24)-
   text    data     bss     dec     hex filename
   1040     484      24    1548     60c try

声明全局变量并用 10- 初始化后
#include <stdio.h>
int i=10;

void main()
{
}

为每个段分配的内存如下(在 Unix 上使用 size 命令)
此处变量“i”已在数据段中接收内存(以前为 484,现在为 488)-
   text    data     bss     dec     hex filename
   1040     488      16    1544     608 try

我的问题是为什么全局变量“i”在存储在 BSS 中时获得了 8 个字节的内存,而在存储在数据段中时获得了 4 个字节?
为什么在BSS和数据段中为整数分配内存有区别?

最佳答案


First, why 4 bytes in data segment?
正如许多人已经回答了这个问题 - .data 段包含任何预先初始化的全局或静态变量。一个整数的大小为 4 个字节,当您的程序中有全局 int i=10; 时,这反射(reflect)在数据段大小中。
Now, why 8 bytes in .bss segment?
由于 默认链接器脚本 的 GNU 链接器 GNU ld ,您正在观察此行为。您可以获得有关链接描述文件 here 的信息。

链接时,GNU 链接器 (GNU ld) 使用默认链接器脚本。

默认链接描述文件指定 .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);
  }

在这里,您可以看到 . = ALIGN(. != 0 ? 64 / 8 : 1); 表示默认对齐为 8 个字节。

该程序:
#include <stdio.h>
int i;

void main()
{
}

使用默认链接器脚本构建时,由于 8 字节对齐,“i”在 BSS 中获得大小为 8 字节的内存:
# size a.out
   text    data     bss     dec     hex filename
   1040     484      24    1548     60c a.out

[bss = 24 字节 (16 + 8)]

GNU 链接器提供了将 您自己的链接器脚本 传递给它的规定,在这种情况下,它使用传递给它的脚本来构建目标,而不是默认链接器脚本。

为了尝试这个,您可以将默认链接器脚本的内容复制到文件中,并使用此命令将链接器脚本传递给 GNU ld :
gcc -Xlinker -T my_linker_script main.c

由于您可以拥有自己的链接器脚本,因此您可以对其进行更改并查看行为的变化。

.bss 部分,将此 . = ALIGN(. != 0 ? 64 / 8 : 1); 更改为 . = ALIGN(. != 0 ? 32 / 8 : 1); 。这会将默认对齐方式从 8 字节更改为 4 字节。现在使用链接描述文件构建您的目标并进行此更改。

输出是:
# size a.out
   text    data     bss     dec     hex filename
   1040     484      20    1544     608 a.out

在这里你可以看到 bss 大小是 20 字节(16 + 4),因为 4 字节对齐。

希望这能回答你的问题。

关于c - 为什么不同大小的内存被分配给 BSS 和数据段中的整数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47455486/

10-11 19:36