一笋鄙、野指針
野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的怪瓶、沒(méi)有明確限制的)指針變量在定義時(shí)如果未初始化萧落,其值是隨機(jī)的,指針變量的值是別的變量的地址,意味著指針指向了一個(gè)地址是不確定的變量找岖,此時(shí)去解引用就是去訪問(wèn)了一個(gè)不確定的地址陨倡,所以結(jié)果是不可知的。
#include <stdio.h>
int main(void)
{
int *p;//當(dāng)前的p就是野指針
*p=4;
//報(bào)錯(cuò) 運(yùn)行時(shí)的段錯(cuò)誤宣增,由野指針造成
}
二玫膀、野指針出現(xiàn)的三種情況
1. 指向不可訪問(wèn)的地址:比如內(nèi)核空間(每個(gè)進(jìn)程都認(rèn)為自己有4G的運(yùn)行空間,但進(jìn)程是共享4G空間爹脾,在每個(gè)進(jìn)程可以尋址的范圍內(nèi)有一部分是操作系統(tǒng)的空間)帖旨,結(jié)果是觸發(fā)段錯(cuò)誤。
2. 指向一個(gè)可用的且沒(méi)有特別意義的空間:比如曾經(jīng)使用過(guò)但無(wú)用的在棧灵妨、堆空間解阅,結(jié)果是沒(méi)有報(bào)錯(cuò),但是有很大的隱患泌霍。
3. 指向了一個(gè)可用的空間货抄,但這個(gè)空間在程序中正在被使用:比如是程序的一個(gè)變量,那么這個(gè)野指針的解引用會(huì)剛好修改這個(gè)變量的值朱转,導(dǎo)致變量被莫名其妙的改變蟹地,導(dǎo)致程序出現(xiàn)離奇多的錯(cuò)誤,最終程序崩潰或者數(shù)據(jù)被損害藤为,這種危害最大的情況怪与。
為什么加了printf函數(shù)后野指針就只可能發(fā)生后兩種情況呢
因?yàn)閜rintf函數(shù)是一個(gè)復(fù)雜函數(shù),不停的申請(qǐng)棧缅疟,棧使用完沒(méi)有被擦除分别。
指針變量如果是局部變量則分配在棧上,反復(fù)使用不會(huì)被擦除存淫,所以是臟的耘斩。棧的使用多少會(huì)影響默認(rèn)值,因此野指針的值是有一定規(guī)律不是完全隨機(jī)桅咆。
三括授、如何避免野指針
指針沒(méi)有明確的指向一個(gè)可用的內(nèi)存空間,然后去解引用導(dǎo)致了野指針岩饼。
在指針的解引用之前確保指針指向一個(gè)絕對(duì)可用的空間刽脖,能夠避免野指針。
1. 定義指針時(shí)同時(shí)初始化為NULL忌愚。
2 . 在指針解引用之前,先去判斷這個(gè)指針是不是NULL却邓。
3. 在指針使用完之后硕糊,將其賦值為NULL。
4. 在指針使用之前將其賦值綁定給一個(gè)可用地址空間。
#include <stdio.h>
int main(void)
{
int a;
int *p=NULL;
int *p=&a;
//中間省略400行.......
if (NULL !=P)
{
*P=4;
}
p=NULL;//使用完后將指針重新定義為NULL
}
實(shí)踐中的處理方法简十,在中小型程序中不必嚴(yán)格參照這個(gè)標(biāo)準(zhǔn)檬某,但在大型程序中建議嚴(yán)格參考這個(gè)原則。
NULL究竟是個(gè)什么
NULL在c中定義為:
#ifdef _cplusplus
#define NULL 0//在c++中NULL就是0
#else
#define NULL (void *)0//在c中NULL是強(qiáng)制類(lèi)型轉(zhuǎn)化為(void *)的0
#endif
在c中int *p;你可以p=(int *)0,但不可以p=0,因?yàn)閏嚴(yán)格要求類(lèi)型相同螟蝙。
NULL的實(shí)質(zhì)就是0恢恼,將指針賦初值給NULL,其實(shí)就是將指針指向0地址處胰默。原因有兩個(gè):
1. 0地址是一個(gè)特殊地址场斑,我們認(rèn)為指針指向這個(gè)地址的為野指針。
2. 這個(gè)地址在一般的操作系統(tǒng)中都是不可被訪問(wèn)的牵署,如果沒(méi)按規(guī)章處理就會(huì)觸發(fā)段錯(cuò)誤漏隐,觸發(fā)段錯(cuò)誤已經(jīng)是野指針造成的最小錯(cuò)誤了。
判斷野指針語(yǔ)句
寫(xiě)成 if (NULL != P),而不是寫(xiě)成if (p != NULL)
原因是如果NULL寫(xiě)在后面當(dāng)中間是==號(hào)時(shí)容易寫(xiě)出=運(yùn)算符,編譯器不會(huì)報(bào)錯(cuò),錯(cuò)誤很難檢查出來(lái)奴迅。所以一般把NULL寫(xiě)在運(yùn)算符前面青责。