內存問題的檢查

#問題 最近在查程序的內存問題,包括前一篇文章也是與此相關《snprintf/_snprintf 在不一樣平臺間函數差別》。 先看一段簡單的程序:php

<!-- lang: cpp -->
int main()
{
    for(int i=0; i<5; i++)
    {
        char k[4];
        char *p = k;
        char b[] = "123456789";

        memcpy(p, b, sizeof(b));
        cout << "in loop" << endl;
    }
    cout << "end" << endl;
    return 0;
}

輸出以下: in loop endhtml

爲什麼循環4次只輸出一次呢?使用gdb查看,發現因爲memcpy越界,直接把變量「i」改爲了一個極大的值。因此一次就結束了。 這段程序極爲兇險的是memcpy越界編譯沒有報錯,執行沒有core dump(若是將數組b改成超大如1000等就可能會dump),而是結果錯誤。設想一下,若是memcpy改了別的什麼內存位置的值,程序如何執行就進入了一個未知的狀況,再加上多線程等複雜的業務場景,就是一顆定時炸彈,平時好好的,而不知什麼時候,就「啵」的爆炸了。而這種狀況查看犯罪現場的core文件,使用bt獲得的已經不是真正問題的所在,而是因爲以前的內存越界致使的正常代碼留下的屍體。java

在複雜的業務邏輯中使用memcpy、strcmp等這種較爲底層的函數,自己就是自討苦吃。代碼量大,開發難度大,通常人寫出的代碼質量不高,出了問題很差查……因此難怪從java到python、php等大行其道。python

如何避免

  1. RAII
  2. 儘可能避免在C++中使用原生數組,以及相關的操做,如memcpy、memset、strcpy等
  3. 使用string、vector等STL來替代。還能夠研究一下auto_ptr等職能指針來減小錯誤~。

出現了怎麼查

  1. 固然仍是人肉看代碼。
  2. 使用工具。cppcheck、Valgrind等來查。

工具用法

  1. 使用Valgrind 動態工具,只支持linux系列,不支持windows。參見《應用 Valgrind 發現 Linux 程序的內存問題》。 實測發現memcpy拷貝的內容長度超過了目的數組的長度時,Valgrind檢查不出來。 使用方便,直接 valgrind [args] program program_argslinux

  2. 使用cppcheck 靜態檢查工具。支持linux、windows。 實測發現能夠發現memcpy拷貝的內容長度超過了目的數組的長度溢出問題。 使用也很方便,cppcheck xxx.cppwindows

這兩個工具要配合使用。數組

ps:cppcheck默認安裝會報錯以下:多線程

(information) Failed to load std.cfg. Your Cppcheck installation is broken, please re-install. The Cppcheck binary was compiled without CFGDIR set. Either the std.cfg should be available in cfg or the CFGDIR should be configured.函數

解決方法: cppcheck的linux安裝須要在make時候對參數CFGDIR配置,設置爲絕對路徑,如:make CFGDIR=/usr/bin/cfg 安裝時候也帶上此參數:make install CFGDIR=/usr/bin/cfg工具

相關文章
相關標籤/搜索