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...