<kbd id="daqct"></kbd>

  • <nav id="daqct"></nav>
    <wbr id="daqct"><pre id="daqct"></pre></wbr>
    <wbr id="daqct"></wbr>
    <form id="daqct"><th id="daqct"></th></form>
    更多課程 選擇中心

    C/C++培訓
    達內IT學院

    400-111-8989

    C++常見內存錯誤及解決方案

    • 發布:C++培訓
    • 來源:C++資訊
    • 時間:2020-03-24 16:38

    C++中內存錯誤通常屬于運行時錯誤,只有在程序運行時才能發現,編譯器無法自動檢測到內存錯誤。多數情況下是程序邏輯或者參數存在某些錯誤。下面總結一下C++常見的內存錯誤:

    1. 內存泄露

    內存泄露是指應用程序未釋放動態申請的且不再使用的內存,原因可能是程序員疏忽或者錯誤造成程序異常。

    在C/C++中,動態申請的內存是在堆上的。內存管理器也不會自動回收不再使用的內存,也就是說如果忘記釋放動態申請的內存,該內存區域是不允許重用的。如果發送此類的內存泄露,函數每執行一次就丟失一塊內存。長時間運行改程序可能引起系統"內存耗盡"。

    這個問題本身沒有很好的解決思路。只能從編程習慣上入手,也就是說動態申請內存與釋放內存必須匹配,亦即new和delete的調用次數必須相同。

    2. 野指針

    未初始化的指針稱為野指針(另一種說法是指向不可用內存區域的指針,不過筆者認為前者更合適)。通常對野指針進行寫操作會發生不可預知的錯誤。

    通常的避免方法就是在指針定義的時候就初始化,初始為NULL或者一個有意義的內存地址。對于動態申請的內存地址,在該內存釋放之后,對應指針最好立即賦值為NULL。并在具體使用指針的時候判斷指針的值是否有效(通常檢測是否為NULL)。

    3. 內存越界訪問

    內存越界訪問通常發生在數組、字符串或者連續內存的訪問。有兩種情況:

    讀越界,即讀了非有效的數據。如果所讀的內存地址是無效的,程序會立即崩潰。如果所讀內存地址是有效的,讀入的時候不會有錯誤,但是讀入的數據是隨機的,可能會產生不可控制的后果。舉個簡單的例子,字符串的輸出,如果沒有結束符,會輸出一堆亂碼也可能輸出正常,也就是說結果是不可控的。

    寫越界,亦稱為緩沖區溢出,通常寫越界會發生錯誤。內存寫越界造成的后果是非常嚴重的。例如訪問數組越界可能會修改訪問數組的循環變量,造成死循環。另一個比較經典的例子就是緩沖區溢出攻擊,試試上就是利用越界修改程序的棧空間,達到控制操作系統或者執行某些特定任務的目的。

    這類問題幾乎沒有很有效的解決思路,只能由程序員控制好內存的訪問,小心處理各種內存有關的操作。

    4. 返回指向臨時變量的指針

    最經典的例子是一道面試題中關于字符串指針的返回函數,代碼如下:

    char * getString(){char b[] = "Hello, Tocy!"; return b;}

    棧里面的變量都是臨時的,函數執行完成之后,相關的臨時變量和參數都會被清除。這也是程序不允許返回指向這些臨時變量的指針的原因,因為函數執行結束后這些指針指向的數據是隨機的,給程序造成不可預知的后果。

    通常此類錯誤編譯器會給出警告。解決思路很簡單,在任何情況下不要返回函數的局部變量的任何指針,如果需要傳遞參數可以考慮使用返回值、參數或者全局變量(不推薦)。

    5. 試圖修改常量

    在普通變量前面加上const修飾符,只是給編譯器做類型檢查用的。編譯器禁止修改這樣的變量,但這并不是強制的,完全可以用強制類型轉換來處理,一般不會出錯。例如下面代碼:

    int func(void){ const int IMAX = 3; int * pi = (int *)(&IMAX); *pi = 4; cout << IMAX << endl;}

    筆者在vc6和vs2008下運行該函數,輸出都是3,編譯運行沒有任何錯誤和警告。至于有沒有修改常量的值,有興趣的讀者可以自己看看反匯編的代碼,相信你就會明白是否修改了常量的值(最終結果是修改了,只是編譯器做了某些優化所以輸出依然不變。)。

    而對于全局常量和字符串使用強制類型轉來處理在運行時仍然會出錯,這是因為它們是存放在只讀內存區("rodata"),只讀內存區是不允許修改的。試圖對其修改,會引發內存錯誤。

    所以針對這種類型錯誤,筆者建議最好不要修改常量,除非萬不得已。

    6. 內存未分配成功,但已經使用

    通常是由于程序員認為動態內存分配不會失敗。解決思路很簡單,在使用動態申請的內存時,首先檢測指針是否為NULL(通常動態內存分配失敗會返回空指針)。

    7. 內存分配成功,但沒有初始化

    犯這種錯誤主要有兩個起因:一是沒有初始化的觀念;二是誤以為內存的缺省初值全為零,導致引用初值錯誤(例如數組)。

    內存的缺省初值究竟是什么并沒有統一的標準,盡管有些時候為零值,我們寧可信其無不可信其有。所以無論用何種方式創建數組,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。

    當然發生這種情況還有另外一個可能就是在動態創建類對象時類構造函數拋出異常(即申請動態內存成功,但是調用構造函數失敗)。

    免責聲明:整理文章為傳播相關技術,版權歸原作者所有,如有侵權,請聯系刪除

    預約申請免費試聽課

    填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

    上一篇:C++培訓學習中的技巧方法
    下一篇:C++編程產生指定范圍內的隨機數

    C語言宏定義的幾種使用方法

    C與C++內存管理避坑指南

    C/C++代碼規范注釋有哪些講究?

    C語言中,全局變量濫用的后果竟如此嚴重?

    • 掃碼領取資料

      回復關鍵字:視頻資料

      免費領取 達內課程視頻學習資料

    • 視頻學習QQ群

      添加QQ群:1143617948

      免費領取達內課程視頻學習資料

    Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

    選擇城市和中心
    黑龍江省

    吉林省

    河北省

    湖南省

    貴州省

    云南省

    廣西省

    海南省

    欧美三级片,白洁外传,第四色播日韩AV第一页,啪啪免费观看大全av 百度 好搜 搜狗
    <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>