未初始化全域性變數,這名字就很直白,就是 c 程式中定義成全域性作用域而又沒有初始化的變數,我們知道這種變數在程式執行後是被自動初始化為 全0 的。編譯器編譯的時候會將這類變數收集起來集中放置到 .bss 段中,這個段只記錄了段長,沒有實際上的內容(全是0,沒必要儲存),在程式被裝載時作業系統會為它分配等於段長的記憶體,並全部初始化為0。
這有兩個 c程式,都定義了全域性陣列 data(長度為1m,占用記憶體4mb),乙個部分初始化(bss_init1.c),乙個未初始化(bss_uninit1.c):
bss_init1.c:
#include #include #define maxlen 1024*1024
int data[maxlen]=;
int main()
bss_uninit1.c:
#include #include #define maxlen 1024*1024
int data[maxlen];
int main()
編譯以上兩個程式後:
可以看到有初始化的可執行檔案的大小差不多是4mb,而未初始化的只有47kb!這就是 .bss 段有段長,而沒有實際內容的表現。用 ultraedit 開啟 bss_init1.exe 可看到檔案中大部分是全0(data陣列的內容):
但是接下來執行(return 0 之前的 sleep(-1) 保證了程式暫時不會退出)的時候,卻發現 bss_init1.exe 占用的空間明顯少於 4mb,這是怎麼回事呢?
這就涉及程式裝載的策略了。早期的作業系統(如:linux 0.01)採用的是一次裝載:將可執行檔案一次性完整裝入記憶體後再執行程式。不管程式是 1kb 還是 60mb,都要等全部裝入記憶體後才能執行,這顯然是不太合理的。
而現在的作業系統都是採用延遲裝載:將程序空間對映到可執行檔案之後就開始執行了,執行的時候如果發現要讀/寫的頁不在記憶體中,就根據對映關係去讀取進來,然後繼續執行應用程式(應該是在頁保護異常的處理中實現的)。
bss_init1.exe 肯定是被映**,而程式中又沒有對 data 陣列進行讀/寫操作,所以作業系統也就懶得去裝入這片記憶體了。下面修改一下這兩個程式:在 sleep(-1) 前將 data 陣列的每個元素賦值為 -1:
int i;
for(i=0; i
再執行,它們占用的記憶體都是 4m 了:
關於未初始化全域性變數
前幾天發現未初始化全域性變數一些特性,後來在一篇部落格上發現有人說過這個問題 這是原博文位址 blog.csdn.net liuqiaoyu080512 article details 8455652 然後結合原博文,自己又做了幾個實驗 以下算是自己實驗一遍以後的總結 首先,自己曾經以為未初化的全域...
C語言全域性變數的初始化
本意是想定義乙個全域性結構體變數,並設定其成變數的值。typedef struct a t a t a a.a 1 error expected asm or attribute before token a.b 2 error expected asm or attribute before to...
區域性變數和全域性變數的初始化
寫 的時候遇到了這個問題,選兩段抄過來做個筆記。定義區域性變數,其實就是在棧中通過移動棧指標來給程式提供乙個記憶體空間和這個區域性變數名繫結。因為這段記憶體空間在棧上,而棧記憶體是反覆使用的 髒的,上次用完沒清零的 所以說使用棧來實現的區域性變數定義時如果不顯式初始化,值就是髒的。在c語言裡,全域性...