[root@localhost]# [root@localhost]# cat -n ./main.c 1 #include參數"-std"的意思是:我要使用的標準 (Standard)是C99的標準;2 3 int main() 4 { 5 char steTemp[321] = { 0x00 }; 6 7 return 0; 8 } [root@localhost]# [root@localhost]# gcc -std=c99 -O0 -Wframe-larger-than=1 ./main.c ./main.c: In function 「main」: ./main.c:8: 警告:the frame size of 336 bytes is larger than 1 bytes [root@localhost]#
參數"-O"的意思是:最佳化 (Optimization)的等級,我要使用0;
參數"-W"的意思是:我要秀出的警告 (Warning)訊息,這裡的設定是"frame-larger-than=1"─訊框的大小要是比1大,就顯示出警告訊息。
可是,我們在這個範例函式裡面,明明就只宣告了321位元組 (Bytes)的字元 (Character)陣列 (Array),為何顯示出來的結果卻是336 Bytes?
因為記憶體對齊 (Memory Alignment),在我的Linux Fedora Core 13的OS上,函式的大小,是以16 Bytes做為對齊的標準。
假設這個函式有傳參數 (Arguments)進來呢?我們可以簡單地修改一下:
[root@localhost]# [root@localhost]# cat -n ./main.c 1 #include咦?這個函式的原本大小應該只有15 Bytes,經過了記憶體對齊之後,變成了16 Bytres;但函式多加了一個參數,函式的大小一點兒都沒變!2 3 int main(int argc) 4 { 5 char steTemp[15] = { 0x00 }; 6 7 return 0; 8 } [root@localhost]# [root@localhost]# gcc -std=c99 -O0 -Wframe-larger-than=1 ./main.c ./main.c: In function 「main」: ./main.c:8: 警告:the frame size of 16 bytes is larger than 1 bytes [root@localhost]#
函式的大小,對於我們的程式設計而言,到底有何用意?因為對於較為嚴謹的編譯器 (Compiler)而言,函式的大小是「不可以」超過作業系統所設定的上限!
假如超過了上限,就會導致系統程式的Pointer Statck Overflow,進而產生Kernel Panic!假如你用add2line或是objdump指令,去分析產生Kernel Panic的源始碼,就算找到發生問題點的程式碼,或是區段 (Block),你把那一段程式碼給改寫了,基本上還是沒有解決問題,你只是暫時先避掉了問題,因為問題的根本原因就是那個函式本身就有問題,今天你先避掉了函式內的A問題點,但那一天同一個函式又會爆出B問題點!
所以,在有些Embedde Linux的make menuconfig的Kernel Space Settings部份,在Kernel Hacking裡會有一個類似"KERNEL_STACK_PROTECTOR"的選項,把它Enable,就可以協助工程師是否有設計出不當的程式。自己看過一些系統廠寫的驅動程式,一個函式裡面全部都用switch - case: ,然後寫了1萬~3萬多行,因為使用了太多的case: 結果每一個case裡面,都用區段:{int a; char b; .... } break; 這種寫法就變得非常、非常地難以Debug,而且也非常危險!
沒有留言:
張貼留言