http://www.cnblogs.com/skynet/archive/2010/12/03/1895045.html 這篇部落格最後寫了5個規則,雖然簡單,但是還是有些問題,在這裡稍作說明。
【規則1】用malloc或new申請記憶體之後,應該立即檢查指標值是否為NULL。防止使 用指標值為NULL的記憶體。
偶評:參考wiki百科針對malloc以及new的說明,對於C語言malloc方式,檢查NULL是可以的,但是對於C++的new操作符 (operator),檢查NULL基本是無用的,因為C++有異常機制,new不成功就會拋異常std::bad_alloc,如何處理可參考 http://msdn.microsoft.com/en-us/library/kftdy56f%28v=VS.71%29.aspx
【規則2】不要忘記為數組和動態記憶體賦初值。防止將未被初始化的記憶體作為右值使用。
偶評:初值的賦值操作也是要花時間的,C語言初始化一塊記憶體memset的時候要注意用buffersize * sizeof(Object),而C++就更複雜了,比如建構函式,new的重載之類,要小心。
【規則3】避免數組或指標的下標越界,特別要當心發生“多1”或者“少1”操作。
偶評:一般來講多一少一運行時不會一定出錯,比如微軟編譯器申請記憶體一般會比你指定的大一些,比如你申請10bytes,如char* p= malloc(10);,通常情況下操作p[10],p[11]啥的是沒有問題的,所以會發生一些奇怪的現象,就是某些bug有人機器會出,有人就無法重 現。
【規則4】動態記憶體的申請與釋放必須配對,防止記憶體流失。
偶評:要說明的是,new一定和delete配對,malloc一定和free配對,否則也會出錯。另外new [],一定要delete [],否則也會泄露。
【規則5】用free或delete釋放了記憶體之後,立即將指標設定為NULL,防止產生 “野指標”。
偶評:這種情況一般是代碼中函數寫的比較長,指標用了又用,或者指標是全域的情況。所以一般軟體公司的編碼規範都會硬性要求這樣做,如果函數很短小 精悍,其實不會有這種擔憂的。當然,偶也同意這樣做有益無害。
再加入一些額外的說明:
對於指標類型的檢查,不應該用assert,而是應該正常操作,if(!p) return E_POINTER;這樣。使用assert的語義與null 指標判斷是兩碼事。如果不想判斷或者圖省事,C++中可以用const reference類型,但是不建議傳入reference對象,然後在函數體內修改。
針對記憶體操作,比如memset,memcpy,同樣要注意不能訪問越界的資料,類似規則3。
針對C++,new delete其實可以做出好多花樣,個人感覺用處不大,因為伺服器端編程大多用C配合記憶體池,重載new之類的學了也很少用。如果對伺服器端記憶體管理感興 趣,可以讀讀nginx的代碼,簡潔高效實用。
一般來講,應該是誰拉的屎誰擦屁股,也就是說某個對象或者函數new了一些東西,它應該負責delete,否則距離不僅僅產生美,還會產生 bug。(多廢話一下,比如在aaa.cpp裡面new了一些東西,然後你在bbb.cpp裡面釋放它,甚至在不同地方釋放它,如果對程式結構不瞭解,很 容易產生bug)
可以通過python或者lua編寫一些小軟體,檢查項目中new與delete,malloc與free的個數,如果個數不匹配,就有可能有 bug,另外還可以檢查new[]與delete[]的配對情況。我編寫了一個這樣的小工具,完善以後放出來。