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!

推薦閱讀: