1. 程式人生 > >bss data rodata text講解

bss data rodata text講解

在ELF格式的可執行檔案中,全域性記憶體包括三種:bss、data和rodata。其它可執行檔案格式與之類似。瞭解了這三種資料的特點,我們才能充分發揮它們的長處,達到速度與空間的最優化。 
1、bss(Block Started by Symbol) 
bss是指那些沒有初始化的和初始化為0的全域性變數和靜態變數,bss型別的全域性變數只佔執行時的記憶體空間,而不佔檔案空間。 
另外,大多數作業系統,在載入程式時,會把所有的bss全域性變數全部清零,無需要你手工去清零。 
但為保證程式的可移植性,手工把這些變數初始化為0也是一個好習慣。 
2、data 


與bss相比,data就容易明白多了,它的名字就暗示著裡面存放著資料。當然,如果資料全是零,為了優化考慮,編譯器把它當作bss處理。通俗的說,data指那些初始化過(非零)的非const的全域性變數和靜態變數。 
由此可見,data型別的全域性變數是即佔檔案空間,又佔用執行時記憶體空間的。 
3、rodata 
rodata的意義同樣明顯,ro代表read only,即只讀資料(const)。只讀資料段,存放常量,字元常量,const常量,據說還存放除錯資訊。關於rodata型別的資料,要注意以下幾點: 
常量不一定就放在rodata裡,有的立即數直接編碼在指令裡,存放在程式碼段(.text)中。 
對於字串常量,編譯器會自動去掉重複的字串,保證一個字串在一個可執行檔案(EXE/SO)中只存在一份拷貝。 
rodata是在多個程序間是共享的,這可以提高空間利用率。 
在有的嵌入式系統中,rodata放在ROM(如norflash)裡,執行時直接讀取ROM記憶體,無需要載入到RAM記憶體中。 
在嵌入式linux系統中,通過一種叫作XIP(就地執行)的技術,也可以直接讀取,而無需要載入到RAM記憶體中。 
由此可見,把在執行過程中不會改變的資料設為rodata型別的,是有很多好處的:在多個程序間共享,可以大大提高空間利用率,甚至不佔用RAM空間。同時由於rodata在只讀的記憶體頁面(page)中,是受保護的,任何試圖對它的修改都會被及時發現,這可以幫助提高程式的穩定性。 
4、text
 

通常是指用來存放程式執行程式碼的一塊記憶體區域。這部分割槽域的大小在程式執行前就已經確定,並且記憶體區域通常屬於只讀, 某些架構也允許程式碼段為可寫,即允許修改程式。在程式碼段中,也有可能包含一些只讀的常數變數,例如字串常量等。 
5、變數與關鍵字 
static關鍵字用途太多,以致於讓新手模糊。不過,總結起來就有兩種作用,改變生命期和限制作用域。如: 
修飾inline函式:限制作用域 
修飾普通函式:限制作用域 
修飾區域性變數:改變生命期 
修飾全域性變數:限制作用域 
const 關鍵字倒是比較明瞭,用const修飾的變數放在rodata裡,字串預設就是常量。對const,注意以下幾點就行了。 
指標常量:指向的資料是常量。如 const char* p = “abc”; p指向的內容是常量 ,但p本身不是常量,你可以讓p再指向”123”。 
常量指標:指標本身是常量。如:char* const p = “abc”; p本身就是常量,你不能讓p再指向”123”。 
指標常量 + 常量指標:指標和指標指向的資料都是常量。const char* const p =”abc”; 兩者都是常量,不能再修改。 
violatile關鍵字通常用來修飾多執行緒共享的全域性變數和IO記憶體。告訴編譯器,不要把此類變數優化到暫存器中,每次都要老老實實的從記憶體中讀取,因為它們隨時都可能變化。這個關鍵字可能比較生僻,但千萬不要忘了它,否則一個錯誤讓你除錯好幾天也得不到一點線索。