内存中的BSS段和DATA段的区别

4
//Global space
int A;
int B = 0;
int C = 0x01;
static int D;
static int E = 0;
static int F = 0x01;

void foo()
{
    static int G;
    static int H = 0;
    static int I = 0x01;
}

我的理解是,所有未显式初始化或初始化为0的全局和静态变量将进入BSS段。而所有用除0以外的任何值初始化的全局和静态变量将进入DATA段。我理解得对吗?

在这种情况下,以下内容是正确的。

A -- BSS (No Explicit init)
B -- BSS (init to 0)
C -- DATA (!= 0)
D -- BSS
E -- BSS
F -- DATA
G -- BSS
H -- BSS
I -- DATA

请纠正我或者回复我。提前感谢。


这完全取决于编译器。 - ikegami
非常奇怪,我以为BSS是用于未初始化的对象,DATA是用于初始化的对象。为什么B、E 和H也在BSS中呢?0是否等同于未初始化? - kiner_shah
是的,您对所有主流系统的理解都是正确的。 - Lundin
@Lundin,这就是我的困惑,难道初始化的对象不应该在数据段中吗? - kiner_shah
2
当初始值为0时,编译器可能会将其放在.bss中而不是.data中以提高效率。C编译器没有使用.data、.bss或任何其他特定段的具体要求 - 这只是一个方便的约定通常被使用。一些实现还使用.common段(一种可怕的想法 - 是与50年前的编译器向后兼容的遗物)。有些实现有许多小段,以允许“更智能”的链接和数据放置。 - David
显示剩余3条评论
2个回答

6

C语言中,所有具有静态存储期的对象都会被初始化。如果您没有编写显式的初始化程序,则将隐式地初始化为零。只有自动存储(在堆栈上)的对象才是真正未初始化的。

这是编译器的观点。如果您选择编辑链接器脚本,则可以得到不同的结果。普通的链接器脚本将执行以下操作:

大多数编译器将C、F和I放在.data中。

大多数编译器将B、D、E、G和H放在.bss中。

唯一有趣的是A;许多编译器将其放在COMMON中。

在GCC中,选项-fno-common将A放在.bss中。

在某些平台上,最近版本的GCC默认启用此选项。


2

1.环境: *nix系统,gcc编译器,ELF(可执行和可链接格式)二进制文件

2.代码: 根据您的代码,下面是一种显示运行时地址的方法:

#include <stdio.h>

//Global space
int A;
int B = 0;
int C = 0x01;
static int D;
static int E = 0;
static int F = 0x01;

void foo()
{
    static int G;
    static int H = 0;
    static int I = 0x01;
    printf("G    : %018p\n",(void *) &G);
    printf("H    : %018p\n",(void *) &H);
    printf("I    : %018p\n",(void *) &I);
}

int main(int argc, char* argv[]) {
    printf("A    : %018p\n",(void *) &A);
    printf("B    : %018p\n",(void *) &B);
    printf("C    : %018p\n",(void *) &C);
    printf("D    : %018p\n",(void *) &D);
    printf("E    : %018p\n",(void *) &E);
    printf("F    : %018p\n",(void *) &F);

    foo();

    return 0;
}

3.提醒:

ELF部分到段的映射:在ELF中,BSS和Data部分将被映射到同一个内存段中:

Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .ctors .dtors .dynamic .got.plt .data .bss 
   04     .dynamic 
   05     .note.tag 
   06     .eh_frame_hdr 
   07     

如您所见,上述的.data.bss段将被映射到段#3

4. ELF符号表

从上面的代码2.中,我们在*nix操作系统上通过gcc进行编译,在ELF二进制文件中可以看到以下表格(按Value字段排序):

Symbol table (.symtab) contains 56 entries:
   Num: Value             Size Type    Bind   Vis      Ndx Name
   ---- ---------------- ----- ------- ------ -------- --- -------------------- 
    24: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crt1_c.c
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    13: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    17: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS mmap.c
    55: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _init_tls@FBSD_1.0
    36: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND atexit@FBSD_1.0
    49: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND exit@FBSD_1.0
    43: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@FBSD_1.0
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
    54: 0000000000400408     0 FUNC    GLOBAL HIDDEN     9 _init
    32: 0000000000400408     0 NOTYPE  LOCAL  DEFAULT    8 __rela_iplt_end
    29: 0000000000400408     0 NOTYPE  LOCAL  DEFAULT    8 __rela_iplt_start
    48: 0000000000400470   263 FUNC    GLOBAL DEFAULT   11 _start
     3: 0000000000400580   283 FUNC    LOCAL  DEFAULT   11 handle_static_init
     2: 00000000004006a0    91 FUNC    LOCAL  DEFAULT   11 finalizer
     7: 0000000000400700     0 FUNC    LOCAL  DEFAULT   11 deregister_tm_clones
     8: 0000000000400730     0 FUNC    LOCAL  DEFAULT   11 register_tm_clones
     9: 0000000000400770     0 FUNC    LOCAL  DEFAULT   11 __do_global_dtors_aux
    12: 00000000004007f0     0 FUNC    LOCAL  DEFAULT   11 frame_dummy
    44: 00000000004007f5    67 FUNC    GLOBAL DEFAULT   11 foo
    51: 0000000000400838   152 FUNC    GLOBAL DEFAULT   11 main
    16: 00000000004008d0     0 FUNC    LOCAL  DEFAULT   11 __do_global_ctors_aux
    39: 0000000000400914     0 FUNC    GLOBAL HIDDEN    12 _fini
    34: 00000000004009a4     0 NOTYPE  LOCAL  DEFAULT   14 __GNU_EH_FRAME_HDR
    15: 0000000000400a48     0 OBJECT  LOCAL  DEFAULT   15 __FRAME_END__
    25: 0000000000600a4c     0 NOTYPE  LOCAL  DEFAULT   16 __fini_array_end
    30: 0000000000600a4c     0 NOTYPE  LOCAL  DEFAULT   16 __fini_array_start
    28: 0000000000600a4c     0 NOTYPE  LOCAL  DEFAULT   16 __init_array_end
    33: 0000000000600a4c     0 NOTYPE  LOCAL  DEFAULT   16 __init_array_start
    27: 0000000000600a4c     0 NOTYPE  LOCAL  DEFAULT   16 __preinit_array_end
    26: 0000000000600a4c     0 NOTYPE  LOCAL  DEFAULT   16 __preinit_array_start
     5: 0000000000600a50     0 OBJECT  LOCAL  DEFAULT   16 __CTOR_LIST__
    14: 0000000000600a58     0 OBJECT  LOCAL  DEFAULT   16 __CTOR_END__
     6: 0000000000600a60     0 OBJECT  LOCAL  DEFAULT   17 __DTOR_LIST__
    41: 0000000000600a68     0 OBJECT  GLOBAL HIDDEN    17 __DTOR_END__
    31: 0000000000600a70     0 OBJECT  LOCAL  DEFAULT   18 _DYNAMIC
    35: 0000000000600bd0     0 OBJECT  LOCAL  DEFAULT   19 _GLOBAL_OFFSET_TABLE_
    53: 0000000000600c08     8 OBJECT  GLOBAL DEFAULT   20 __progname
    42: 0000000000600c10     0 OBJECT  GLOBAL HIDDEN    20 __dso_handle
    45: 0000000000600c18     4 OBJECT  GLOBAL DEFAULT   20 C
    20: 0000000000600c1c     4 OBJECT  LOCAL  DEFAULT   20 F
    23: 0000000000600c20     4 OBJECT  LOCAL  DEFAULT   20 I.0
    38: 0000000000600c24     0 NOTYPE  GLOBAL DEFAULT   20 _edata
    50: 0000000000600c24     0 NOTYPE  GLOBAL DEFAULT   21 __bss_start
    52: 0000000000600c28     0 OBJECT  GLOBAL HIDDEN    20 __TMC_END__
    40: 0000000000600c28     8 OBJECT  GLOBAL DEFAULT   21 environ
    10: 0000000000600c30     1 OBJECT  LOCAL  DEFAULT   21 completed.1
    11: 0000000000600c38     8 OBJECT  LOCAL  DEFAULT   21 dtor_idx.0
    46: 0000000000600c40     4 OBJECT  GLOBAL DEFAULT   21 A
    37: 0000000000600c44     4 OBJECT  GLOBAL DEFAULT   21 B
    18: 0000000000600c48     4 OBJECT  LOCAL  DEFAULT   21 D
    19: 0000000000600c4c     4 OBJECT  LOCAL  DEFAULT   21 E
    21: 0000000000600c50     4 OBJECT  LOCAL  DEFAULT   21 G.2
    22: 0000000000600c54     4 OBJECT  LOCAL  DEFAULT   21 H.1
    47: 0000000000600c58     0 NOTYPE  GLOBAL DEFAULT   21 _end

您看到的是:

  • data 包含 C,F 和 I
  • bss 包含 A,B,D,E,G 和 H

5.答案

看起来您的假设是正确的。


感谢Valery对如何查看他们的地址空间的解释和额外提示。 - Sudhakar M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接