記憶體陷阱 馴服C 中的野指標

2021-04-12 21:14:26 字數 1858 閱讀 6448

什麼是野指標?

乙個母親有兩個小孩(兩個指標),乙個在廚房,乙個在臥室,(屬於不同的**塊,其生存期不同)母親讓在廚房的小孩帶一塊蛋糕(指標指向的物件)給在臥室的小孩,這樣在臥室的孩子才肯寫作業。但這個在廚房的小孩比較淘氣,他在走出廚房時自己將蛋糕吃了,沒能帶出來。而在臥室的沒有吃到蛋糕,所以不肯完成他的作業。結果母親卻不知道臥室的孩子沒有吃到蛋糕,還以為作業完了。結果第二天她就被老師召喚到辦公室了。事情麻煩了。

這樣,那個在臥室的孩子就是野指標了,因為他沒有得到應得的蛋糕,不能完成母親交給他的作業。

這就是c中所講的野指標。上面的小劇本不過演示了一種最基本的野指標的形成過程。更容易出現的情形是coder在編碼時,大意之下使用了已經free過的指標。

對於年輕點的經驗欠缺的coder來說是比較容易犯的錯誤,經驗老到的程式設計師或者慎重採取成對程式設計的形式避免這種失誤,或者使用引用計數器防止形成野指標。

總之,在c中,野指標也許性子野,但是控制起來也是有章可循。然而事情在c++中出現了變化。

coder們面臨更大的麻煩了。c++程式設計師無可避免的要寫很多這樣那樣的類。誰讓c++是物件導向的呢?

我們在寫類的時候難免要用new給類的資料成員分配記憶體。這本來沒什麼,動態分配記憶體是一種很常見的基本操作,我們在學資料結構時經常這麼做,不是麼?

但是夥計,事情並非這麼簡單。類是一種高階的使用者自定義資料型別,看起來和結構、列舉這樣的使用者自定義型別沒啥太大差別。如果你這樣認為....?那你會死的很慘。類太複雜了,普通情況下使用類的物件並沒有太大的問題,但是,當你要複製乙個物件時,問題就來了。

比如我們知道,你要用乙個物件初始化另乙個物件時,c++是按位進行拷貝的,即在目標物件裡建立了初始化物件的乙個完全相同的拷貝。這在多數情況下已經足夠了。但是,當你的類在建立時為每個物件分配記憶體,也就是說類中有new操作。當你的物件建立好後,類也為物件分配了一塊記憶體。如果你用這個物件去初始化另乙個物件時,被初始化的物件和初始化的物件完全一樣。這意味著,他們使用同一塊記憶體,而不是重新為被初始化的物件分配記憶體。

可以說,這就是c++中更加**的野指標。

什麼?你說我不用物件初始化物件?那麼我們會不會將乙個物件作為變元傳遞給函式呢?我們很多時候都這樣做。有時我們不得不將物件按值傳遞給乙個函式,但是你要知道,按值傳遞是什麼意思?它的意思就是,把實參的乙個拷貝傳遞給函式。這和剛才的初始化沒什麼兩樣,按位拷貝,函式體內的物件與外面的物件共用一塊記憶體,即便在函式中的物件沒有對這塊記憶體進行過操作,但是當函式結束時。。。。析構函式將會被呼叫......

還有一種與之相反的情況......, 當你想要把乙個在函式內的物件值返回給外面的物件時,這時候,會自動產生乙個臨時物件,由它容納函式的返回值,並在函式結束時把結果傳給目標。那麼這個臨時物件迅速的被建立,並被迅速的釋放。。。一塊記憶體被釋放了兩次。其後果是不可預見的。

當你把乙個物件的值賦給另乙個物件時,如果你沒有過載賦值運算子,那麼也會導致按位拷貝。最終產生乙個野指標(乙個隱藏在類內的毒瘤),或者釋放同一塊記憶體多次。

看到了麼?害怕了麼?是不是感到c++到處都是陷阱呢?不但有陷阱,到處都是危險品。所有c中的疑難問題,到了c++就成了一般問題了。好了不廢話了,我們繼續講講解決之道。

對於最後的這種賦值的情況,我們只有通過過載賦值運算子才能解決,也就是避免按位拷貝。

至於前面的都屬於初始化,概括下來就是三種情況:

1.當乙個物件初始化另乙個物件時,例如在宣告中;

2.把所建立的物件拷貝(按值)傳遞給乙個函式時;

3.生成臨時物件時,最常見的就是函式的返回值。

解決初始化時的按位拷貝問題,我們通過建立拷貝建構函式來解決。

基本的拷貝建構函式形式為:

classname (const classname &o)

拷貝建構函式就是針對這個問題而設計的。

恩,大家都明白了吧?不要讓你的物件都變成可憐的連體人啊~~~~

記憶體陷阱 馴服C 中的野指標

我們知道,c 將記憶體劃分為三個邏輯區域 堆 棧和靜態儲存區。既然如此,我稱位於它們之中的物件分別為堆物件,棧物件以及靜態物件。那麼這些不同的記憶體物件有什麼區別了?堆物件和棧物件各有什麼優劣了?如何禁止建立堆物件或棧物件了?這些便是今天的主題。一 基本概念 先來看看棧。棧,一般用於存放區域性變數或...

C語言記憶體(野指標 )

1.堆 在鍊錶中找接近4位元組的空間,發現 5位元組接近 4位元組,將 5位元組給程式。2.靜態儲存區 編譯時就存在 儲存全域性變數和靜態區域性變數 3.野指標 1 區域性指標變數沒有初始化 struct student char name int number int main struct st...

C 中記憶體釋放,防止野指標出現

new型別 一維陣列 int data intnew len 釋放記憶體 delete data data nullptr 二維陣列 int data intnew row for int i 0 i 釋放記憶體 for int i 0 i delete data data nullptr mall...