熟女俱乐部五十路二区av,又爽又黄禁片视频1000免费,国产卡一卡二卡三无线乱码新区,中文无码一区二区不卡αv,中文在线中文a

"); //-->

博客專欄

EEPW首頁 > 博客 > C語言常見內(nèi)存錯(cuò)誤及解決方法

C語言常見內(nèi)存錯(cuò)誤及解決方法

發(fā)布人:電子禪石 時(shí)間:2020-08-12 來源:工程師 發(fā)布文章
常見的錯(cuò)誤      

關(guān)于內(nèi)存的一些知識已在內(nèi)存分配中提及,現(xiàn)記錄與分享常見的內(nèi)存錯(cuò)誤與對策。

類型 1:內(nèi)存未分配成功,卻使用了它。

方   法:在使用之前檢查指針是否為NULL。

             1)當(dāng)指針p是函數(shù)的參數(shù)時(shí),在函數(shù)入口處用語句assert(p!=NULL)進(jìn)行斷言檢查。

             2)當(dāng)使用malloc或new來申請內(nèi)存時(shí),應(yīng)該用if(p != NULL)進(jìn)行防錯(cuò)檢查。

類型 2:引用了尚未初始化的指針

原   因:內(nèi)存的缺省初始值究竟是什么并沒有統(tǒng)一的標(biāo)準(zhǔn),在使用之前都進(jìn)行初始化。

              1)沒有初始化的觀念。

              2)內(nèi)存的缺省值是未定義,即垃圾值。

類型 3:越界操作內(nèi)存

原   因:內(nèi)存分配成功且初始了,但越界操作是不允許的。

例   如:在使用數(shù)組時(shí)經(jīng)常發(fā)生下標(biāo)“多1”或“少1”,特別是在for循環(huán)語句時(shí)。

類型 4:忘記釋放內(nèi)存,造成內(nèi)存泄漏。

原   因:含有這種類型錯(cuò)誤的函數(shù),每被調(diào)用一次,就丟失一塊內(nèi)存。當(dāng)內(nèi)存充足時(shí)看不到這種錯(cuò)誤帶來的影響,當(dāng)內(nèi)存耗盡時(shí)系統(tǒng)提示:“內(nèi)存耗盡”。因此,動態(tài)內(nèi)存的申請與釋放必須配對,程序中malloc與free的使用次數(shù)要相同。

類型 5:釋放了內(nèi)存卻繼續(xù)使用它

原   因:對應(yīng)的情況有2種

              1)返回了“棧內(nèi)存的指針或引用”,因?yàn)槎褩V械淖兞吭诤瘮?shù)結(jié)束后自動銷毀。

              2)某塊內(nèi)存被free后,沒有將指向該內(nèi)存的指針設(shè)置為NULL,導(dǎo)致產(chǎn)生“野指針”。

使用規(guī)則

      為了保證代碼的健壯和安全,可以參考如下的規(guī)則

規(guī)則1:使用malloc申請的內(nèi)存時(shí),必須要立即檢查相對應(yīng)的指針是否為NULL。

規(guī)則2:初始化數(shù)組和動態(tài)內(nèi)存。

規(guī)則3:避免數(shù)組或指針下標(biāo)越界。

規(guī)則4:動態(tài)內(nèi)存的申請和釋放必須相配對,防止內(nèi)存泄漏。

規(guī)則5:free釋放某塊內(nèi)存之后,要立即將指針設(shè)置為NULL,防止產(chǎn)生野指針。

 

幾個(gè)重要的概念:

1.野指針

       概念:“野指針”不是NULL指針,是指指向“垃圾”內(nèi)存的指針。即指針指向的內(nèi)容是不確定的。

       產(chǎn)生的原因:1)指針變量沒有初始化。因此,創(chuàng)建指針變量時(shí),該變量要被置為NULL或者指向合法的內(nèi)存單元。

                             2)指針p被free之后,沒有置為NULL,讓人誤以為p是個(gè)合法的指針。

                             3)指針跨越合法范圍操作。不要返回指向棧內(nèi)存的指針或引用

例子1-1:引用尚未初始化的指針

[cpp] view plain copy


  1. char *p;  

  2. *p = 'A';//error,p指向未定義  

 

 

例子1-2:return語句返回指向“棧內(nèi)存”的指針

 

[cpp] view plain copy


  1. char *GetString1(void)  

  2. {  

  3.     char p[] = "hello world!";  

  4.     //p在棧區(qū),常量字符串在常量字符區(qū)  

  5.   

  6.     return p;//error,返回棧內(nèi)存的地址  

  7. }  

char p[] =
一個(gè)數(shù)組,這個(gè)數(shù)組是局部變量。

char* p =
一個(gè)指針,這個(gè)指針指向一個(gè)字符串常量

區(qū)別在于:數(shù)組的話,字符串是存在于這個(gè)數(shù)組里的,因?yàn)檫@個(gè)數(shù)組屬于局部變量,所以你就算把數(shù)組的地址返回給主函數(shù),主函數(shù)也沒有辦法再訪問這個(gè)地址了。
但是如果是指向字符串常量的指針,這個(gè)字符串是放在程序的常量區(qū)而不是放在局部變量中,那么你把這個(gè)常量的地址返回給主函數(shù),主函數(shù)也還是可以訪問它的。

char* p是一個(gè)指針,根本沒分配內(nèi)存,他指向的"hello world" 是一個(gè)地址,而且地址不用加“”
而char p[]是一個(gè)數(shù)組,已經(jīng)分配內(nèi)存,是將"hello world" 復(fù)制到該內(nèi)存里面,這個(gè)內(nèi)存是可讀寫的

 

例子1-3:使用了被釋放的內(nèi)存

[cpp] view plain copy


  1. char *pstr = (char *)malloc(sizeof(char)*100);  

  2. free(pstr); //pstr所指的內(nèi)存被釋放  

  3. if (NULL !=pstr)//沒起到作用  

  4. {  

  5.     strcpy(pstr,"string!");//error,有時(shí)候程序不會提示有誤,但還是不允許  

  6. }  

 

注意:free()釋放的是指針指向的內(nèi)存!不是指針變量!這點(diǎn)非常非常重要!指針是一個(gè)變量,只有程序結(jié)束時(shí)才被銷毀。釋放了內(nèi)存空間后,原來指向這塊空間的指針還是存在!只不過現(xiàn)在指針指向的內(nèi)容的垃圾,是未定義的,所以說是垃圾。因此,前面我已經(jīng)說過了,釋放內(nèi)存后把指針指向NULL,防止指針在后面不小心又被解引用。

對比下面的例子,加深理解

例子1-4:函數(shù)返回值傳遞動態(tài)內(nèi)存

[cpp] view plain copy


  1. char* GetMemory(int num)  

  2. {  

  3.     char *p = (char *)malloc(sizeof(char) * num);  

  4.     return p ;//ok,返回堆區(qū)的地址值  

  5. }  

 

例子1-5:

[cpp] view plain copy


  1. char *GetString(void)  

  2. {  

  3.     char *p = "hello world!";  

  4.     //指針變量p在棧區(qū),指向文字常量區(qū)的字符  

  5.   

  6.     return p;//ok,返回字符串的地址  

  7. }  

2.內(nèi)存泄漏

    概念:用動態(tài)內(nèi)存分配函數(shù)動態(tài)開辟的空間,在使用完畢后未釋放,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元,直到程序結(jié)束。

注意:內(nèi)存泄漏是指堆內(nèi)存的泄漏。它的一般表現(xiàn)方式是程序運(yùn)行時(shí)間越長,占用內(nèi)存越多,最終用盡全部內(nèi)存,整個(gè)系統(tǒng)崩潰。

例子2-1:內(nèi)存泄漏,共9*100字節(jié)發(fā)生泄漏

[cpp] view plain copy


  1. void Test(void)  

  2. {  

  3.     char *p = NULL;  

  4.     for ( int i = 0; i<10; i++)  

  5.     {  

  6.         p = (char*)malloc(100);//沒循環(huán)一次內(nèi)存泄漏一塊,最后一次得到正確使用  

  7.     }  

  8.       

  9.     strncpy(p,"string!");  

  10.     free(p);  

  11. }  

3.內(nèi)存溢出

   概念:系統(tǒng)分配的內(nèi)存不足以放下數(shù)據(jù),稱為內(nèi)存溢出。

例子3-1:運(yùn)行時(shí)提示出錯(cuò)

 

[cpp] view plain copy


  1. char str[10]={0};  

  2.   

  3. strcpy(str,"hello world!");//error!  

  4.  


https://blog.csdn.net/qq_38211852/article/details/80085591

*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。



關(guān)鍵詞:

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉