bss段不佔據磁碟空間的理解

2021-07-30 02:59:05 字數 2043 閱讀 7456

elf檔案中.bss段:

存放未初始化的全域性變數,將.data和.bss分開的理由是為了節約磁碟空間,.bss不佔實際的磁碟空間。這句話該怎麼理解呢?

可以看下面的例子:

#include int a[1000];

int b[1000] = ;

int main()

這裡編寫了乙個test.c的檔案,gcc編譯gcc test.c -o test之後,使用ls -l test命令可以得到可執行檔案的資訊,我們只關注檔案的大小為12608。

使用命令size test檢視各個段的大小(不包含stack和heap段):

接著我們修改源程式:

#include int a[1000] = ;

int b[1000] = ;

int main()

編譯之後,使用ls -l test命令再次檢視可執行檔案的資訊

使用命令size test檢視段的大小

可以看到大小從12608變成了16608,與之前相對比,該檔案佔據的大小漲了4000位元組,這不就是我們的陣列a[1000]的大小嗎?我們所在的改動僅僅是初始化了a[1000],讓這個陣列的所在段從.bss段改到了.data段。通過size test命令檢視bss段的大小也減小了。這就證明了.bss段中的資料並沒有佔據磁碟空間,從而節約了磁碟的空間。

當程式載入執行時,就會為.bss段中的資料分配記憶體已經進行初始化了。

下面還有兩個疑問,那就是int a[1000]既然不佔據實際的磁碟空間(是指不佔據應該分配的記憶體大小),那麼它的大小和符號存在哪呢?

.bss段佔據的大小存放在elf檔案格式中的段表(section table)中,段表存放了各個段的各種資訊,比如段的名字、段的型別、段在elf檔案中的偏移、段的大小等資訊。

我們可以通過命令readelf -s test來檢視test可執行檔案的段表(這裡只擷取了一部分):

這裡再額外說明乙個很有趣的地方,在elf檔案結構中,有乙個字串表.strtab,裡面存放的是elf檔案中各個段的名字以及變數名等字串,字串表中記錄了這些字串以及對應的下標,需要用到這些字串時,直接用偏移下標去取就行了。段表中存放的段的名字這一項,就是存的.strtab中對應字串的偏移。

.bss段所佔空間的大小存在**解決了,那麼就剩下符號了。

符號當然對應的存在符號表.symtab中了。

我們可以通過命令readelf -s test來檢視:

在第49行,我們看到了定義的全域性陣列b[1000]4000那一項表明資料的大小是4000位元組,object代表是乙個變數,global代表是作用域是全域性的。

最後我們總結一下:

.bss不佔據實際的磁碟空間,只在段表中記錄大小,在符號表中記錄符號。當檔案載入執行時,才分配空間以及初始化。

delete之後,快速清理表佔據的磁碟空間!

收縮innodb儲存引擎表的空間大小 delete 了6000w日誌表記錄,但是表佔據的檔案大小一直沒有變化。後來,找到一招 alter table x engine innodb 搞定,而且速度很很快。mysql alter table order action engine innodb que...

delete之後,快速清理表佔據的磁碟空間!

收縮innodb儲存引擎表的空間大小 delete 了6000w日誌表記錄,但是表佔據的檔案大小一直沒有變化。後來,找到一招 alter table x engine innodb 搞定,而且速度很很快。mysql alter table order action engine innodb que...

關於bss段的理解

bss不佔據程式可執行程式大小,只在段表中記錄大小,在符號表中記錄符號。當檔案載入執行時,才分配空間以及初始化。bss段的大小,記錄在段表裡裡,記錄的是所有未初始化變數總共的大小,bss段只在段表裡有個記錄,但實現並不存在這個段.static int g static short int h int...