日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

【C语言进阶深度学习记录】三十七 C/C++中造成程序内存错误的原因(野指针)

發(fā)布時(shí)間:2023/12/10 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C语言进阶深度学习记录】三十七 C/C++中造成程序内存错误的原因(野指针) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

什么是野指針? 指針變量存的地址是一塊非法內(nèi)存地址。進(jìn)而形成野指針。但是需要注意一點(diǎn),野指針不是NULL指針。

文章目錄

    • 1 野指針的概念
      • 1.1 野指針代碼案例初探
    • 2 如何避免野指針
      • 2.1 野指針代碼案例分析進(jìn)階
    • 3 總結(jié)

1 野指針的概念

  • 野指針變量中的值是非法內(nèi)存地址,進(jìn)而形成野指針
  • 野指針不是NULL指針,是指向不可用內(nèi)存的地址的指針
  • NULL指針并無(wú)危害,很好判斷,也很好調(diào)試
  • C語(yǔ)言的語(yǔ)言層面無(wú)法判斷一個(gè)指針?biāo)4娴牡刂肥欠袷呛戏ǖ摹?/li>

那么野指針是如何產(chǎn)生的呢?

以下在代碼中的編程不規(guī)范會(huì)導(dǎo)致野指針的產(chǎn)生:

  • 局部指針變量沒(méi)有被初始化(我們知道局部變量不初始化就是隨機(jī)值,所以如果局部指針被賦為隨機(jī)值,那么這個(gè)隨機(jī)值所代表的地址很有可能是不能訪問(wèn)的,是非法的地址。那么它就是野指針)
  • 指針?biāo)赶虻淖兞吭谥羔槺皇褂弥氨讳N(xiāo)毀。比如在函數(shù)的返回值是指針。在函數(shù)返回后,函數(shù)的調(diào)用棧就被銷(xiāo)毀了,接著使用被返回的指針時(shí),這個(gè)指針?biāo)赶虻膬?nèi)存已經(jīng)被銷(xiāo)毀,所以形成野指針
  • free指針后,還依然使用指針,這也是野指針
  • 進(jìn)行了錯(cuò)誤的指針運(yùn)算和錯(cuò)誤的強(qiáng)制類(lèi)型轉(zhuǎn)換(后面代碼案例會(huì)分析)
  • 1.1 野指針代碼案例初探

    • 代碼41-1.c
    #include <stdio.h> #include <malloc.h>int main() {int* p1 = (int*)malloc(40);int* p2 = (int*)1234567;int i = 0;for(i=0; i<40; i++){*(p1 + i) = 40 - i;}free(p1); for(i=0; i<40; i++){p1[i] = p2[i];}return 0; }
    • 使用gcc4.4.5編譯器編譯上述代碼:上述代碼編譯沒(méi)有問(wèn)題,運(yùn)行會(huì)出現(xiàn)段錯(cuò)誤。如果使用較新版本的編譯器,可能編譯都會(huì)直接報(bào)錯(cuò)。
    • 分析錯(cuò)誤原因:

    段錯(cuò)誤一般就是野指針問(wèn)題:

  • 首先第8行將1234567強(qiáng)制轉(zhuǎn)換為int*指針變量并賦值給p2。然后在第29行使用p2。1234567這個(gè)地址,肯定是不能訪問(wèn)的。所以p2就是野指針。所以運(yùn)行時(shí)訪問(wèn)p2指針指向的內(nèi)存就會(huì)產(chǎn)生段錯(cuò)誤
  • 16行已經(jīng)將指針p1的內(nèi)存釋放。但是在20行又使用p1.這也是野指針,會(huì)造成段錯(cuò)誤
  • 第13行中,因?yàn)閜1在第7行只申請(qǐng)了40字節(jié)也就是10個(gè)int的內(nèi)存。所以13行使用p1加了40次,肯定會(huì)越界訪問(wèn)了本不是p1申請(qǐng)的內(nèi)存。這也會(huì)造成段錯(cuò)誤
  • 2 如何避免野指針

    遵循以下幾條規(guī)則,避免野指針的產(chǎn)生

  • 絕不在函數(shù)中返回局部指針變量或者局部數(shù)組
  • 任何變量在定義后,必須先初始化
  • 字符數(shù)組必須確認(rèn)最后一個(gè)元素是‘\0’結(jié)束符才能將該數(shù)組當(dāng)成是字符串,否則不能將其當(dāng)成字符串。因?yàn)樽址乃胁僮鞫际腔谧詈蟮摹痋0’結(jié)束符,如果沒(méi)有這個(gè)結(jié)束符,很有可能在操作字符串的時(shí)候產(chǎn)生內(nèi)存越界
  • 任何使用與內(nèi)存操作相關(guān)的函數(shù)必須指定長(zhǎng)度信息。在C語(yǔ)言中,長(zhǎng)度信息很重要,它往往是變量類(lèi)型的一部分。如數(shù)組。如下圖:
  • 2.1 野指針代碼案例分析進(jìn)階

    • 代碼41-2.c
    #include <stdio.h> #include <string.h> #include <malloc.h>struct Student {char* name; //這里有指針,很容易忘記初始化int number; };char* func() {char p[] = "D.T.Software";return p; //返回局部數(shù)組/指針,gcc4.4.5編譯器會(huì)編譯警告 }void del(char* p) {printf("%s\n", p);free(p); //free之后要將p置NULL }int main() {struct Student s; //s中有指針變量,這里沒(méi)有初始化,容易產(chǎn)生野指針char* p = func(); // 返回的指針指向的內(nèi)存已經(jīng)被銷(xiāo)毀strcpy(s.name, p); //p指向的內(nèi)存已經(jīng)被銷(xiāo)毀不能使用,且s中的name指針沒(méi)有初始化也會(huì)產(chǎn)生野指針s.number = 99;p = (char*)malloc(5);strcpy(p, "D.T.Software"); //內(nèi)存越界del(p);return 0; }
    • 上述代碼編譯就會(huì)產(chǎn)生警告。警告第15行返回局部指針。程序運(yùn)行產(chǎn)生段錯(cuò)誤
    • 其他的會(huì)產(chǎn)生野指針的地方在代碼中已經(jīng)詳細(xì)的說(shuō)明。自己分析即可。

    3 總結(jié)

    • 知道野指針的由來(lái)以及如何避免產(chǎn)生野指針。這是非常重要的!!!

    總結(jié)

    以上是生活随笔為你收集整理的【C语言进阶深度学习记录】三十七 C/C++中造成程序内存错误的原因(野指针)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。