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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

c++野指针小结

發(fā)布時(shí)間:2023/12/8 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++野指针小结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.什么是野指針

所謂野指針(wild pointer),簡單講是指指向不可用的內(nèi)存區(qū)域的指針。需要注意的一點(diǎn)是,野指針與NULL空指針是不同的。NULL指針一般比較好判斷,直接用if (p==NULL)語句判斷即可。但是野指針指向的是垃圾內(nèi)存區(qū)域的指針,一旦使用往往會(huì)造成不可預(yù)測(cè)的結(jié)果,這種隨機(jī)不可預(yù)測(cè)的結(jié)果才是最可怕的。

2.未初始化

造成野指針最常見的情況之一就是指針未被正確初始化。任何指針在被創(chuàng)建的時(shí)候,不會(huì)自動(dòng)變成NULL指針,他的default值是隨機(jī)的。所以一個(gè)比較好的習(xí)慣是,指針剛創(chuàng)建的時(shí)候,要么設(shè)置為NULL空指針,要么指向合理的內(nèi)存區(qū)域。

看一下一個(gè)簡單例子

void func() {int* p;cout<<*p<<endl; }

我們?cè)趍ain方法中調(diào)用該函數(shù),會(huì)得到輸出

1901647869

不難看出得到的就是一個(gè)隨機(jī)值。

3.懸垂指針

懸垂指針也是野指針常見的一種。當(dāng)我們顯式地從內(nèi)存中刪除一個(gè)對(duì)象或者返回時(shí)通過銷毀棧幀,并不會(huì)改變相關(guān)的指針的值。這個(gè)指針實(shí)際仍然指向內(nèi)存中相同位置,甚至該位置仍然可以被讀寫,只不過這時(shí)候該內(nèi)存區(qū)域完全不可控,因?yàn)槟悴荒鼙WC這塊內(nèi)存是不是被別的程序或者代碼使用過。

void dangling_point() {char *p = (char *)malloc(10);strcpy(p, "abc");cout<<p<<endl;free(p);if (p != NULL) cout<<p<<endl;strcpy(p, "def"); }

我們執(zhí)行free§語句時(shí),p所指向的內(nèi)存被釋放,此時(shí)該內(nèi)存區(qū)域變成不可用內(nèi)存。但是,p此時(shí)指向的地址并沒有發(fā)生改變,而且也不會(huì)為空,所以if(p != NULL)判斷為真,會(huì)繼續(xù)執(zhí)行后面的語句。
但是strcpy(p, “def”); 這一句,雖然代碼不會(huì)報(bào)錯(cuò)崩潰,但此時(shí)正在篡改動(dòng)態(tài)內(nèi)存區(qū),會(huì)產(chǎn)生不可預(yù)料的結(jié)果,此操作相當(dāng)危險(xiǎn),尤其是debug時(shí)候非常不好排查,往往會(huì)讓人崩潰…

為了避免懸垂指針的問題,一般做法是在free/delete指針以后,再將p=NULL,這樣就可以避免上述問題。

4.返回棧內(nèi)存指針或引用

看一個(gè)例子

int* return_ret() {int result = 1;return &result; }int main(int argc, char const *argv[]) {int *p = return_ret();cout<<*p<<endl;cout<<*p<<endl;return 0; }

首先,這段代碼能編譯通過。不過IDE會(huì)提醒warning:

test_code.cc:80:13: warning: address of stack memory associated with local variable 'result' returned [-Wreturn-stack-address]return &result;^~~~~~ 1 warning generated.

什么意思?就是我們返回了一個(gè)局部變量的棧內(nèi)內(nèi)存地址。
代碼也能正常運(yùn)行:

1 32767

我們注意看,第一個(gè)打印語句,甚至還能輸出"正確"的結(jié)果1。
但是到了第二個(gè)打印語句,此時(shí)輸出的結(jié)果就不可控了,因?yàn)榇藭r(shí)該內(nèi)存區(qū)域的內(nèi)容,已經(jīng)發(fā)生了變化。此時(shí)該內(nèi)存地址已經(jīng)變得不"可靠",操作該內(nèi)存區(qū)域?qū)?huì)相當(dāng)危險(xiǎn)。

5.特殊的空指針

空指針為一特殊指針,是唯一一個(gè)對(duì)任何指針類型都合法的指針值。為了提高程序可讀性,標(biāo)準(zhǔn)庫定義了一個(gè)與0等價(jià)的符號(hào)常量NULL。p = 0;p = NULL;都是把p置為空指針值,上面兩種寫法等價(jià)。

6.free操作的真相

以下部分內(nèi)容來自網(wǎng)絡(luò):

內(nèi)存管理有以下幾個(gè)層次(從高到低):C程序 - C庫(malloc)- 操作系統(tǒng) - 物理內(nèi)存

首先,操作系統(tǒng)保證每個(gè)進(jìn)程都有獨(dú)立的虛擬內(nèi)存空間(32bit上應(yīng)該是4G吧,一般進(jìn)程也用不了這么多)。當(dāng)然實(shí)際上物理內(nèi)存是所有進(jìn)程共享的,所以當(dāng)你需要?jiǎng)討B(tài)內(nèi)存時(shí),需要向操作系統(tǒng)申請(qǐng),這時(shí)候雖然從你程序的角度,內(nèi)存是連續(xù)的,其實(shí)是被操作系統(tǒng)映射到某一塊物理內(nèi)存而已。程序用完內(nèi)存歸還后,實(shí)際歸還的部分可能被操作系統(tǒng)分配給其他進(jìn)程。

要注意,上面說的“歸還”是malloc庫的行為。malloc庫會(huì)使用一些策略來提高內(nèi)存使用的效率,比如程序需要使用10K內(nèi)存時(shí),malloc實(shí)際可能上會(huì)申請(qǐng)1M,因?yàn)橐淮蜗到y(tǒng)調(diào)用開銷很大;再比如即使你調(diào)用了free“歸還“了程序使用的內(nèi)存,malloc庫也可能并未真正把這些內(nèi)存歸還給操作系統(tǒng),因?yàn)閷沓绦蚩赡苓€會(huì)再申請(qǐng)動(dòng)態(tài)內(nèi)存。

malloc庫有多種實(shí)現(xiàn),我知道的一種是使用標(biāo)記(tag)來存儲(chǔ)內(nèi)存的元信息。比如你申請(qǐng)了8個(gè)byte,得到的頭指針地址是0x1001(實(shí)際內(nèi)存為0x1001-0x1008),malloc會(huì)在0x1000(也就是頭指針-1的位置)保存8,即這段內(nèi)存的長度。等釋放時(shí),程序?qū)㈩^指針地址傳給free,malloc庫從頭指針-1的位置發(fā)現(xiàn)需要釋放的內(nèi)存長度,釋放內(nèi)存(實(shí)際的操作可能只是將tag清空)。這就解釋了:1. 為什么和malloc不同,free的參數(shù)只有一個(gè)頭指針而不需要長度;2. free后內(nèi)存實(shí)際上可能并未歸還給操作系統(tǒng)。

所以,訪問被(程序)釋放的內(nèi)存是一種undefined行為,就是說結(jié)果是不確定的。在malloc庫未將此內(nèi)存歸還給操作系統(tǒng)也未進(jìn)行下一次動(dòng)態(tài)分配時(shí),這塊內(nèi)存事實(shí)上仍屬于程序。而當(dāng)malloc庫不清理歸還的內(nèi)存時(shí)(多數(shù)實(shí)現(xiàn)都是如此),你能訪問到的值仍是原來的值。這和函數(shù)調(diào)用完畢而未清理?xiàng)⒑罄m(xù)調(diào)用函數(shù)可以訪問到之前已經(jīng)設(shè)置的局部變量值是一個(gè)道理。

但是,當(dāng)malloc庫已經(jīng)將內(nèi)存歸還給系統(tǒng)時(shí),再去訪問原來的地址(更別說寫),由于這段地址已經(jīng)不屬于程序了,就會(huì)出現(xiàn)經(jīng)典的segmentation fault。

說到底,這些現(xiàn)象還是C語言庫為了更有效率的實(shí)現(xiàn)而妥協(xié)的結(jié)果。

總結(jié)

以上是生活随笔為你收集整理的c++野指针小结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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