C語言基礎野指針與空指針示例分析
一:野指針
概念:野指針就是指向的內存地址是未知的(隨機的,不正確的,沒有明確限制的)。
說明:指針變量也是變量,是變量就可以任意賦值。但是,任意數值賦值給指針變量沒有意義,因為這樣的指針就成瞭野指針,此指針指向的區域是未知(操作系統不允許操作此指針指向的內存區域)。
註:野指針不會直接引發錯誤,操作野指針指向的內存區域才會出問題。
代碼示例:
int a = 100; int *p; p = a; //把a的值賦值給指針變量p,p為野指針, ok,不會有問題,但沒有意義 p = 0x12345678; //給指針變量p賦值,p為野指針, ok,不會有問題,但沒有意義 *p = 1000; //對野指針進行賦值操作就不可以瞭
把a的值賦值給指針變量p,p為野指針, ok,不會有問題,但沒有意義。
給指針變量p賦值,p為野指針, ok,不會有問題,但沒有意義。
野指針的成因
1. 指針未初始化
指針變量剛被創建時不會自動成為NULL指針,它的缺省值是隨機的,它所指的空間是隨機的。
代碼示例:
int main() { int * p; *p = 20; return 0; }
(個人理解:指針變量有操作系統隨機賦值,未指向一個具體空間,沒有落腳點)
2. 指針越界訪問
指針指向的范圍超出瞭合理范圍,或者調用函數時返回指向棧內存的指針或引用,因為棧內存在函數結束時會被釋放。
代碼示例:
int main() { int arr[10] = {0}; int *p = arr; for(int i = 0; i <= 11; i++) { *(P++) = i;//當指針指向的范圍超出數組arr的范圍,p變成野指針。 } return 0; }
3 .指針釋放後未置空
有時指針在free或delete後未賦值 NULL,便會使人以為是合法的。其實它們隻是把指針所指的內存給釋放掉,但並沒有把指針本身忘記。此時指針指向的就是無效內存。釋放後的指針應立即將指針置為NULL,防止產生“野指針”。
代碼示例:
int main() { int *p = NULL; p = malloc(10 * sizeof(int)); if (!p) { return; } //成功開辟內存,可以操作內存。 free(p); p = NULL; return 0; }
(個人理解:我們前一天住瞭個賓館,第二天退房瞭,雖然我們知道一個該房間的門牌號,但是保潔阿姨已經收拾瞭房間,我們就不知道房間裡具體是什麼樣的瞭,所以我們也沒法操作瞭。)
規避野指針
1. 初始化指針
代碼示例:
int main() { int *p = NULL; int a = 10; p = &a; *p = 20; return 0; }
2. 避免指針越界
代碼示例:
int main() { int arr[10] = {0}; int *p = arr; for(int i = 0; i < 10; i++) { *(P++) = i;//嚴格遵守有效范圍。 } return 0; }
3 避免返回局部變量的地址
代碼示例:
int * test() { int a = 20; return &a; } int main() { int *p = NULL; p = test(); printf("%d\n", *p); return 0; }
這與變量的作用域有關,局部變量存在棧區,當被調函數結束後 ,棧區上局部變量的內存空間被釋放,若再去訪問該空間就不合理瞭。
4. 開辟的指針釋放後置為NULL
當指針p指向的內存空間釋放時,沒有設置指針p的值為NULL。free隻是把內存空間釋放瞭,但是並沒有將指針p的值賦為NULL。
代碼示例:
int main() { int *p = NULL; p = malloc(10 * sizeof(int)); if (!p) { return; } //成功開辟內存,可以操作內存。 free(p); p = NULL;//避免野指針 return 0; }
5. 養成良好的編程習慣
好的編程習慣可以避免很多問題,道阻且長,但行則將至!!!
二:空指針
*NULL是一個值為0的宏常量:#define NULL ((void )0)
意義:為瞭標志指針變量沒有指向任何變量(空閑可用),在C語言中,通常把NULL賦值給此指針,這樣就標志此指針為空指針,沒有指向任何空間。
註意:對指針解引用操作可以獲得它所指向的值。但從定義上看,NULL指針並未指向任何東西,因為對一個NULL指針解引用是一個非法的操作,所以在解引用之前,必須確保它不是一個NULL指針。
代碼示例:
void test(){ char *p = NULL; **//給p指向的內存區域拷貝內容** strcpy(p, "1111"); //err char *q = 0x1122; //給q指向的內存區域拷貝內容 strcpy(q, "2222"); //err }
OK!!!觀眾老爺們,這裡隻是介紹瞭野指針與空指針,如果朋友們覺得有一點點作用的話,希望朋友們能夠給予小菜鳥一點支持!後續繼續給朋友們帶來更好的博文,還希望朋友們能夠繼續關註,小菜鳥致力於把自己的學習經驗與個人理解更多的分享給大傢,望大傢喜歡與指正,希望大傢以後多多支持WalkonNet!