全局内存BSS,DATA,RODATA的区别以及其他内存区间相关
剛接觸c語言的時候,了解了全局變量這個概念,只知道所謂全局變量的意思就是代碼文件里面所有的函數都可以隨時調用修改的變量,而其實這種理解是十分不準確的,但隨著后期學習的深入,接觸了計算機組成原理和匯編的相關知識,通過閱讀其他大神的博客,學到了很多,發現所謂全局變量其實是存放在全局內存中的變量,以及很重要的一點就是強調全局,這個所謂的全局指的是變量的生命周期,而不是他的作用域,先前的理解誤區正是將全局理解為僅指作用域。
static:使用static聲明的變量,他可能是在某一個函數中進行申明,這時可以說這個變量的作用范圍是局部的,但是生命周期是全局的。
一般而言,定義在一起的兩個全局變量在內存中位置是相鄰的,這局簡單的話有時很有用,比如一個全局變量受到了破壞,那么程序中定義位置前后數組或是其他元素可能出現了越界訪問,代碼排錯的時候可以快速縮小錯誤位置區間。
BSS:
如果一個全局變量沒有被初始化 或者被初始化為0,那么這個全局變量就被存放在bss內存中。
這種類型的全局變量的特點:
作如下變量聲明:
int bssTest[1024*1024]={0};
編譯鏈接結束后,查看可執行文件大小,遠小于4M,這說明bss類的全局變量不占用文件存儲空間而只占用程序運行內存空間。
對于大多數的操作系統,在程序加載的時候會自動的將在所有bss全局變量清零,無需手動清零,但是手動清零是一種很好的編程習慣。
DATA:
正如其名:數據。
data內存放那些初始化過的非const全局變量,當然如果初始化為0,編譯器還是會被把他當作bss來處理。
對于其特點,與BSS對應來看,同樣在代碼中也做如下聲明:
int dataTest[1024*1024]={1};
編譯鏈接結束查看可執行文件大小發現大小為4M+,于是,data全局變量占用文件空間也占用運行內存空間。
RODATA
:所謂RO,read only,只讀,也就是只允許讀取而不允許修改的意思。
對于RODATA類的數據:
- 常量不一定就放在RODATA內,?有的立即數直接編碼在指令里,存放在代碼段中(text)。
- 字符串常量在經過編譯器處理的時候會被自動去掉重復字符串,保證一格字符串在一個可執行文件中只有一份拷貝。
- RODATA是?多線程共享內存?,這樣做的好處就是可以提高空間的利用率。
- 有的嵌入式系統中,rodata放在ROM中(norflash),運行時直接加載ROM而無須加載到RAM中。
- 嵌入式linux系統中有一種技術叫做?XIP(就地執行)?,同樣能實現直接讀取而無須加載到RAM中。
把運行過程中不會發生改變的數據放到rodata區是有很多好處的,多線程共享,提升空間利用率甚至不占用RAM空間,以及rodata的只讀屬性在某些情況下可以阻止意外的數據破壞,能夠提升程序運行的穩定性。
上面提到了static關鍵字,其實static關鍵字的作用就是改變生命周期和限制作用域
對于const關鍵字:
使用const的常量放在rodata里面,字符串默認是常量:有如下定義:
char *p = “hello world!”;
const char *p = “hello world!”;
這兩種聲明,無論是上者還是下者,當試圖使用p指針去修改字符串內容的時候都會提示錯誤,字符串所在位置都是靜態區,但是p指針本身所在位置有區別
這個就涉及了另外的問題:
- 指針常量和常量指針的問題(修飾就近原則):
指針常量:指向的數據是常量,這里我做如下定義:
const char *p = {hello};//這種定義下const修飾char *p也就是p指針指向的內容,既p指向的字符串作為常量放在bss,而指針p并不是常量,我們還可以改變他的指向,讓它指向別的字符串。
常量指針,顧名思義,指針是常量,定義方式如下:
char *const p = {hello};//p本事就是一個常量,只能指向hello\0這個字符串而不能改變。
內存的其他區域:
heap堆區:這個區域用來存儲使用malloc分配的內存空間,使用完以后需要使用free手動釋放來管理存儲空間,雖然程序退出后OS也會自動釋放。
stack棧區:這一部分的存儲空間是編譯器在編譯代碼的時候就分配好點的固定存儲空間
總結
以上是生活随笔為你收集整理的全局内存BSS,DATA,RODATA的区别以及其他内存区间相关的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈TCP优化
- 下一篇: bss,data,text,rodata