为什么在BSS和数据段中将不同大小的内存分配给整数?

时间:2017-11-23 12:22:21

标签: c unix memory memory-management

请完成以下程序 -

#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和数据段中为内存分配内存存在差异?

1 个答案:

答案 0 :(得分:1)

  

为什么全局变量&#39; i&#39;当它存储在BSS中时获得了大小为8字节的内存,但当它存储在数据段中时却得到了4个字节?

First, why 4 bytes in data segment?

许多人已经回答过这个问题 - .data段包含任何事先初始化的全局变量或静态变量。整数的大小为4个字节,当您的程序中包含全局int i=10;时,它将反映在数据段大小中。

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()
{
}

使用默认链接描述文件构建时,&#39; i&#39;由于8字节对齐,在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

由于4字节对齐,您可以看到bss大小为20字节(16 + 4)。

希望这能回答你的问题。