PS:http://stackoverflow.com/questions/16557677/difference-between-data-section-and-the-bss-section-in-c

The .bss section is guaranteed to be all zeros when the program is loaded into memory. So any global data that is uninitialized, or initialized to zero is placed in the .bss section. For example:

static int g_myGlobal = 0;     // <--- in .bss section

The nice part about this is, the .bss section data doesn't have to be included in the ELF file on disk (ie. there isn't a whole region of zeros in the file for the .bss section). Instead, the loader knows from the section headers how much to allocate for the .bss section, and simply zero it out before handing control over to your program.

Notice the readelf output:

[ 3] .data PROGBITS 00000000 000110 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 000110 000000 00 WA 0 0 4

.data is marked as PROGBITS. That means there are "bits" of program data in the ELF file that the loader needs to read out into memory for you. .bss on the other hand is marked NOBITS, meaning there's nothing in the file that needs to be read into memory as part of the load.


Example:

// bss.c
static int g_myGlobal = 0; int main(int argc, char** argv)
{
return 0;
}

Compile it with $ gcc -m32 -Xlinker -Map=bss.map -o bss bss.c

Look at the section headers with $ readelf -S bss

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
:
[13] .text PROGBITS 080482d0 0002d0 000174 00 AX 0 0 16
:
[24] .data PROGBITS 0804964c 00064c 000004 00 WA 0 0 4
[25] .bss NOBITS 08049650 000650 000008 00 WA 0 0 4
:

Now we look for our variable in the symbol table: $ readelf -s bss | grep g_myGlobal

37: 08049654     4 OBJECT  LOCAL  DEFAULT   25 g_myGlobal

Note that g_myGlobal is shown to be a part of section 25. If we look back in the section headers, we see that 25 is .bss.


To answer your real question:

Here in the above program I dont have any un-intialised data but the BSS has occupied 8 bytes. Why does it occupy 8 bytes ?

Continuing with my example, we look for any symbol in section 25:

$ readelf -s bss | grep 25
9: 0804825c 0 SECTION LOCAL DEFAULT 9
25: 08049650 0 SECTION LOCAL DEFAULT 25
32: 08049650 1 OBJECT LOCAL DEFAULT 25 completed.5745
37: 08049654 4 OBJECT LOCAL DEFAULT 25 g_myGlobal

The third column is the size. We see our expected 4-byte g_myGlobal, and this 1-byte completed.5745. This is probably a function-static variable from somewhere in the C runtime initialization - remember, a lot of "stuff" happens before main() is ever called.

4+1=5 bytes. However, if we look back at the .bss section header, we see the last column Al is 4. That is the section alignment, meaning this section, when loaded, will always be a multiple of 4 bytes. The next multiple up from 5 is 8, and that's why the .bss section is 8 bytes.


Additionally We can look at the map file generated by the linker to see what object files got placed where in the final output.

.bss            0x0000000008049650        0x8
*(.dynbss)
.dynbss 0x0000000000000000 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
*(.bss .bss.* .gnu.linkonce.b.*)
.bss 0x0000000008049650 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
.bss 0x0000000008049650 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crti.o
.bss 0x0000000008049650 0x1 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtbegin.o
.bss 0x0000000008049654 0x4 /tmp/ccKF6q1g.o
.bss 0x0000000008049658 0x0 /usr/lib/libc_nonshared.a(elf-init.oS)
.bss 0x0000000008049658 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtend.o
.bss 0x0000000008049658 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crtn.o

Again, the third column is the size.

We see 4 bytes of .bss came from /tmp/ccKF6q1g.o. In this trivial example, we know that is the temporary object file from the compilation of our bss.c file. The other 1 byte came from crtbegin.o, which is part of the C runtime.


Finally, since we know that this 1 byte mystery bss variable is from crtbegin.o, and it's named completed.xxxx, it's real name is completed and it's probably a static inside some function. Looking at crtstuff.c line 362 we find the culprit: a static _Bool completed inside of __do_global_dtors_aux().

[转] .bss段和.data段的区别的更多相关文章

  1. bss段和data段的区别

    一般情况下,一个程序本质上都是由 bss段.data段.text段三个组成的——本概念是当前的计算机程序设计中是很重要的一个基本概念.而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大 ...

  2. [转帖]浅谈程序中的text段、data段和bss段

    作者:百问科技链接:https://zhuanlan.zhihu.com/p/28659560来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 一般情况,一个程序本质上都 ...

  3. (深入理解计算机系统) bss段,data段、text段、堆(heap)和栈(stack)

    bss段: bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域. bss是英文Block Started by Symbol的简称. bss段属于静态内存分配. ...

  4. 【转】(深入理解计算机系统) bss段,data段、text段、堆(heap)和栈(stack)

    bss段: bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域. bss是英文Block Started by Symbol的简称. bss段属于静态内存分配. ...

  5. Linux中的段管理,bss段,data段,

    Linux 的段管理, BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存 ...

  6. [转] bss段、data段、text段

    1.前言 一个程序本质上都是由 BSS 段.DATA段.TEXT段三个组成的. 本文主要分编译时和运行时分别对 对data段 bss段 text段 堆 栈作一简要说明 2. 程序编译时概念说明 程序与 ...

  7. Text段、Data段和BSS段

    不同的compiler在编译的过程中对于存储的分配可能略有不同,但基本结构大致相同. 大体上可分为三段:Text段.Data段和BSS段. text段用于存放代码,通常情况下在内存中被映射为只读,但d ...

  8. 代码中函数、变量、常量 / bss段、data段、text段 /sct文件、.map文件的关系[实例分析arm代码(mdk)]

    函数代码://demo.c #include<stdio.h> #include<stdlib.h> , global2 = , global3 = ; void functi ...

  9. Linux段管理,BSS段,data段,.rodata段,text段

    近期在解决一个编译问题时,一直在考虑一个问题,那就是Linux下可执行程序执行时内存是什么状态,是依照什么方式分配内存并执行的.查看了一下资料.就此总结一下,众所周知.linux下内存管理是通过虚存管 ...

随机推荐

  1. JS字符串常用方法

      // 来自 http://www.runoob.com/js/js-strings.html   var str01 = "odd open xboxone" , str02 ...

  2. 关于一个隐藏和显示物品列表的demo

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  3. nginx反向代理取得IP地址

    nginx反向代理后,在应用中取得的ip都是反向代理服务器的ip,取得的域名也是反向代理配置的url的域名,解决该问题,需要在nginx反向代理配置中添加一些配置信息,目的将客户端的真实ip和域名传递 ...

  4. python学习第十七天 --定制类

    何为定制类? Python的class允许定义许多特殊方法,可以让我们非常方便地生成特定的类.在类中应用或者重写python的特殊方法,得到的类,就是定制类. 大家都知道print的用法.见下面例子 ...

  5. C语言itoa函数和atoi 函数

    C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串.以下是用itoa()函数将整数转 换为字符串的一个例子: # include <stdio.h>  ...

  6. ubuntu后台运行命令行

    ubuntu 程序后台运行几个方法 . 程序后加上“&” ,即 “./myjob &”, 将命令放入到一个作业队列中,可以用命令“jobs” 查看 . 将1中的命令放在 “()”中, ...

  7. Java中匿名类的两种实现方式(转)

    使用匿名内部类课使代码更加简洁.紧凑,模块化程度更高.内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到.然而这个不是我说的重点,我说的很简单,就是匿名内部类的两种实现方式 ...

  8. 收藏maven错误

    错误原因: 编译下载最新的maven源代码,但是出现错误.错误如下: [WARNING] Some problems were encountered while building the effec ...

  9. 【HDOJ】4325 Flowers

    树状数组+离散化的题目,一直在思考为什么结果不一样,后来才发现花开了就是开了不会再谢了. /* 4325 */ #include <iostream> #include <cstdi ...

  10. 【转】探讨android更新UI的几种方法----不错

    原文网址:http://www.cnblogs.com/wenjiang/p/3180324.html 作为IT新手,总以为只要有时间,有精力,什么东西都能做出来.这种念头我也有过,但很快就熄灭了,因 ...