青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

為你寫詩

c/c++
隨筆 - 32, 文章 - 0, 評論 - 3, 引用 - 0
數(shù)據(jù)加載中……

C++編碼中減少內(nèi)存缺陷的方法和工具

原文:http://baitai.iteye.com/blog/1086202
摘 要:基于C++的軟件的缺陷和錯誤大部分都和內(nèi)存相關(guān),預(yù)防、發(fā)現(xiàn)、消除代碼中和內(nèi)存相關(guān)的缺陷,成為程序員編寫、調(diào)試、維護(hù)代碼時的重要任務(wù)。該文基于“面向網(wǎng)絡(luò)海量空間信息的大型GIS”課題的工程實踐,提出和總結(jié)了如何使用C++語言機制、開發(fā)環(huán)境和相關(guān)質(zhì)量保證工具來預(yù)防、發(fā)現(xiàn)各種編譯期、運行期內(nèi)存缺陷的方法和工具。

關(guān)鍵詞:C++;內(nèi)存錯誤;內(nèi)存泄漏;質(zhì)量保證

Techniques and Tools of Defending Memory-related Defects in Software Coded in C++
CHENG Zhenlin, FANG Jinyun, TANG Zhimin
(Institute of Computing Technology, Chinese Academy of Sciences, Beijing 100080)
【Abstract】Most of the defects and errors in the software coded in C++ are memory-related. Based on the practice in the "network, large volumespatial information oriented GIS" project, this paper presentsthe techniques and tools to find and fix the memory problems during the coding,debugging and production release phase with the support of the C++ language mechanism, development environment and related quality-assurancetools.
【Key words】C++; Memory errors; Memory leak; Quality assurance

C++語言是桌面系統(tǒng),尤其是系統(tǒng)軟件、大型應(yīng)用軟件的主流開發(fā)語言。C++語言以其靈活性著稱,同時也更復(fù)雜。利用C++編寫健壯的代碼,更具有挑戰(zhàn)性。C++允許動態(tài)內(nèi)存管理, 同時也容易導(dǎo)致更多和內(nèi)存相關(guān)的問題。一般而言, 除了系統(tǒng)設(shè)計上的缺陷, 基于C++的軟件的缺陷和錯誤大部分都和內(nèi)存缺陷(主要包括內(nèi)存訪問錯誤和內(nèi)存泄漏兩類)相關(guān)。 所以,消除代碼中的內(nèi)存相關(guān)缺陷,成為程序員編寫、調(diào)試、維護(hù)代碼中的任務(wù),也是保證軟件質(zhì)量的關(guān)鍵。
本文的工作基于“863”計劃項目“面向網(wǎng)絡(luò)海量空間信息的大型GIS”課題。該系統(tǒng)是基于C++/MFC編寫,開發(fā)環(huán)境是Visual Studio .net 2003。本文基于此項目的工程實踐,總結(jié)了如何使用C++語言機制、開發(fā)環(huán)境和相關(guān)質(zhì)量保證工具來預(yù)防、發(fā)現(xiàn)各種編譯期、運行期和內(nèi)存相關(guān)的缺陷的方法和工具。
1 遵循C++相關(guān)的編碼規(guī)范和慣用法,預(yù)防缺陷
編碼規(guī)范是語言相關(guān)的規(guī)則,是經(jīng)過實踐總結(jié)出來的經(jīng)驗。良好的編程標(biāo)準(zhǔn)將有效地幫助開發(fā)人員避免開發(fā)有潛在危險的代碼。一般來說,為了減少內(nèi)存缺陷,應(yīng)該遵循下列編碼規(guī)則[1]:
(1)基類或者帶有虛函數(shù)的類應(yīng)該將其析構(gòu)函數(shù)聲明為虛函數(shù)。
(2)在構(gòu)造函數(shù)中防止內(nèi)存泄漏,在析構(gòu)函數(shù)中不要拋出異常。
(3)使用對應(yīng)形式的new和delete。即:用delete來釋放new申請的內(nèi)存,delete[]釋放new[]申請的內(nèi)存。
(4)指針在使用前必須初始化,指向動態(tài)內(nèi)存的指針在釋放后應(yīng)立即置為空。
(5)如果類構(gòu)造函數(shù)中分配了資源,那么需要顯式提供拷貝構(gòu)造函數(shù)和賦值操作符,并且在析構(gòu)函數(shù)中釋放資源。
值得重視的是C++中的慣用法RAII。RAII核心思想是利用對象來管理資源,在對象的構(gòu)造函數(shù)中獲取資源,在其析構(gòu)函數(shù)中釋放資源[2]。為了保證動態(tài)申請的內(nèi)存能在即使出現(xiàn)異常的情況下仍能釋放,比較理想的方法是使用局部變量來管理動態(tài)內(nèi)存的所有權(quán)(ownership),就是所謂的智能指針。STL中的auto_ptr就是為解決資源所有權(quán)問題設(shè)計的,但是缺少對引用數(shù)和數(shù)組的支持并且不能用在STL容器中。Boost庫[3]提供的智能指針相對成熟,實用價值高。其中,shared_ptr線程安全并且可以用在STL容器中。具體示例參考文獻(xiàn)[3]。
1.1 編碼規(guī)范檢查工具 CodeWizard
CodeWizard能夠?qū)υ闯绦蛑苯舆M(jìn)行自動掃描、分析和檢查。一旦發(fā)現(xiàn)違例,產(chǎn)生信息告知與哪條規(guī)則不符并作出解釋。以CodeWizard 4.3 為例,其中內(nèi)置了超過500條編碼標(biāo)準(zhǔn)。CodeWizard可以選擇對于當(dāng)前的工程執(zhí)行哪些編碼標(biāo)準(zhǔn)。CodeWizard可以和VC++緊密集成,安裝完畢以后,VC++中有CodeWizard工具條。
1.2 代碼檢查工具 PC-Lint
PC-Lint可檢查編譯器不易發(fā)現(xiàn)的錯誤。PC-Lint可對100多個C庫函數(shù)進(jìn)行檢查,可以發(fā)現(xiàn)標(biāo)準(zhǔn)C/C++代碼中的1 000多個常見錯誤。要把PC-lint和Visual Studio集成在一起,需要自己配置。Jon Zyzyck提供了一個報告生成器,可以幫助完成這個工作。可在http://www.ddj.com下載。文獻(xiàn)[4]說明了如何在VC++環(huán)境中集成PC-Lint。
2 利用語言機制、開發(fā)環(huán)境和相關(guān)工具以預(yù)防和發(fā)現(xiàn)內(nèi)存缺陷
發(fā)現(xiàn)問題是解決問題的前提。相對于修復(fù)內(nèi)存缺陷,發(fā)現(xiàn)內(nèi)存缺陷并準(zhǔn)確定位導(dǎo)致缺陷的代碼更為費時費力。及早準(zhǔn)確地發(fā)現(xiàn)內(nèi)存缺陷,對于提高開發(fā)效率非常重要。
2.1 利用斷言及早暴露內(nèi)存缺陷
斷言是布爾調(diào)試語句,用來檢測在程序運行的時候某一條件的值是否總為真。斷言經(jīng)常用來確認(rèn)函數(shù)的輸入、輸出,檢查對象的當(dāng)前狀態(tài)是否合法等。 在以下的場景使用斷言可以幫助發(fā)現(xiàn)和內(nèi)存非法訪問相關(guān)的錯誤:
(1)驗證指針是否可讀/寫。在函數(shù)的入口處,經(jīng)常需要驗證指針?biāo)赶虻膬?nèi)容區(qū)域是否可讀/寫。 通常采用assert(p!= NULL)的檢測形式。 但是,指針的值不為空并不代表指針指向了合法可讀/寫內(nèi)存。Win32 API提供了函數(shù)IsBadReadPtr、IsBadWritePtr、IsBadStringPtr、IsBadCodePtr用來檢測指針指向的內(nèi)存區(qū)域是否可讀/寫。C運行時庫提供了_CrtIs ValidPointer、_CrtIsValidHeapPointer等函數(shù),MFC庫提供了AfxIsValidAddress、AfxIsValidString函數(shù)來完成類似功能。
(2)對基于MFC的程序,ASSERT_VALID宏通過調(diào)用重載的AssertValid函數(shù)來確定指向CObject派生類對象的指針是否有效。ASSERT_VALID宏主要調(diào)用了AfxIsValidAddress函數(shù)和CObject派生類對象的AssertValid函數(shù)(參考MFC源代碼afx.h、objcore.cpp)。
2.2 利用C運行時刻庫檢查內(nèi)存泄漏
VC++的C運行庫(CRT)提供了廣泛的功能,幫助用戶檢測內(nèi)存泄漏。CRT提供了_CrtMemCheckPoint、_CrtDump MemoryLeaks、_CrtSetDbgFlag等函數(shù)來幫助調(diào)試內(nèi)存泄漏。
對于非MFC的工程, 要開啟有效的內(nèi)存泄漏報告功能, 需要進(jìn)行如下設(shè)置:

(1)在StdAfx.h的頭部添加如下代碼并開啟編譯器/Yu 選項:

 #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #define DEBUG_NEW new(_NORMAL_BLOCK, THIS_FILE, __LINE__)

(2)確保在每個.cpp文件的頭部包含以下內(nèi)容:
 #include "stdafx.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif

(3)在程序的開始處開啟報告內(nèi)存泄漏的開關(guān):
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
對于MFC工程, MFC已經(jīng)做了相關(guān)的工作, 只需要確認(rèn)在每個.cpp文件的頭部包含上述第(2)點的內(nèi)容。
在某些情況下,需要知道發(fā)生內(nèi)存泄漏的內(nèi)存塊中的內(nèi)容,但是標(biāo)準(zhǔn)的內(nèi)存轉(zhuǎn)儲只是內(nèi)存塊頭部的十六進(jìn)制形式。為了得到更多的有用信息,需要以用戶塊類型(_CLIENT_ BLOCK)申請內(nèi)存,并利用_CrtSetDumpClient建立用戶塊型內(nèi)存的轉(zhuǎn)儲函數(shù)。具體的說,對于不是從CObject繼承的類,需要:

(1)為每個類/結(jié)構(gòu)指定一個用戶塊子類型(參考crtdbg.h)。

(2)在申請內(nèi)存時,采用重載的new形式:void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine)(參考MFC源代碼 afxmem.cpp),其中nType就是用戶塊的子類型。

(3)創(chuàng)建一個用戶塊內(nèi)存轉(zhuǎn)儲函數(shù),專門對每種需要轉(zhuǎn)儲的子類型進(jìn)行處理(需要包含dbgint.h)。

(4)利用_CrtSetDumpClient對用戶塊內(nèi)存轉(zhuǎn)儲函數(shù)進(jìn)行注冊(參考MFC源代碼dumpinit.cpp)。

對于從CObject繼承來的類,MFC 已經(jīng)按照上述方法做了基礎(chǔ)工作(參考MFC源代碼 afxmem.cpp、dumpinit.cpp)。要有效轉(zhuǎn)儲從CObject繼承的對象,需要:(1)對每個從CObject繼承的類重載虛函數(shù)Dump。(2)在程序的初始化部分 加入代碼 afxDump.SetDepth(1)來開啟深度轉(zhuǎn)儲。

2.3 利用Purify和Insure++查找運行時內(nèi)存缺陷
Rational Purify和Parasoft Insure++ 是用于運行時錯誤檢查的工具。Purify主要檢測:數(shù)組內(nèi)存越界讀/寫,使用未初始化的內(nèi)存,對已釋放的內(nèi)存進(jìn)行讀/寫,內(nèi)存泄漏等。Insure++利用其專利技術(shù)(源碼插裝和運行時指針跟蹤)能夠發(fā)現(xiàn)大量的內(nèi)存操作錯誤,報告錯誤的源代碼行和執(zhí)行軌跡。根據(jù)筆者的測試(基于98個有各種內(nèi)存錯誤的C++程序,涵蓋了典型情形),Insure++ 6.1都能準(zhǔn)確檢測。
3 利用VC++環(huán)境的調(diào)試和診斷功能,檢查和發(fā)現(xiàn)常見內(nèi)存缺陷
理解常見的內(nèi)存缺陷問題以及在VC++環(huán)境下的癥狀,能輔助我們減少問題的發(fā)生和及時修改問題。
從錯誤的表現(xiàn)形式上看, 和堆棧有關(guān)的錯誤主要分為兩大類:堆棧溢出和函數(shù)返回信息被破壞。

(1)堆棧溢出(overflow)

此類錯誤主要有兩種情形:

1)過大的局部變量。缺省情況下Windows為每個線程保留1M堆棧空間。在菜單Project->Properties->Configuration Properties -> Linker->System中可以看到Stack Reserve Size選項可以調(diào)整保留的堆棧空間大小。

2)遞歸調(diào)用層數(shù)過深。在調(diào)試過程中,調(diào)用堆棧(call stack)窗口中可以發(fā)現(xiàn)函數(shù)遞歸調(diào)用的模式。

(2)函數(shù)返回信息被破壞

此類錯誤主要有兩種情形:
1)對局部變量的寫操作超出了范圍(上溢)。在調(diào)試過程中,函數(shù)堆棧被破壞掉的明顯標(biāo)志是無法顯示調(diào)用堆棧,并且錯誤發(fā)生在被調(diào)用函數(shù)即將返回的位置。
2)在調(diào)用函數(shù)和被調(diào)用函數(shù)之間如果出現(xiàn)了函數(shù)參數(shù)的不匹配或者調(diào)用規(guī)范的不一致。
為了檢查此類錯誤,應(yīng)該在代碼編譯時打開/GS、/RTCs開關(guān)(在菜單Project->Properties->Configuration Properties-> C/C++->Code Generation下設(shè)置)。
另外一類錯誤是動態(tài)內(nèi)存錯誤。典型的情況如下:
(1)內(nèi)存寫越界。在調(diào)試版本中,如果是寫上溢,就會收到“Damage:after block...”的跟蹤消息,如果是寫下溢出就會收到“Damage: before block...”的跟蹤消息。
(2)刪除不合法指針。在調(diào)試版本中,刪除未初始化的指針或者非堆指針時,會收到_CrtIsValidHeapPointer斷言錯誤。
(3)多次釋放。在調(diào)試版本中,如果多次刪除同一指針, 會收到_BLOCK_TYPE_IS_VALID斷言錯誤。要防止此類錯誤,應(yīng)在delete某個指向動態(tài)內(nèi)存的指針后立即將其置為空。

4 利用Windows結(jié)構(gòu)化異常處理機制處理發(fā)布版本軟件的內(nèi)存崩潰
在程序的發(fā)布階段,應(yīng)盡量減少程序錯誤尤其是內(nèi)存崩潰。如果崩潰了,應(yīng)該“優(yōu)雅”地退出,盡量收集程序崩潰時的運行信息以幫助程序供應(yīng)商后續(xù)的調(diào)試。要捕捉內(nèi)存非法訪問并獲知非法訪問的指令地址、寄存器內(nèi)容等信息,需要用到Windows的結(jié)構(gòu)化異常處理(Structured Exception Handling,SEH)機制[6]。MiniDumpWriteDump是dbghelp.dll提供的一個 API函數(shù)(參考MSDN),用于轉(zhuǎn)儲用戶模式程序的一些信息(比如堆棧情況等)并存為一個文件(比如.dmp文件),此文件可以被微軟的調(diào)試器(VC++或者WinDBG)利用進(jìn)行事后調(diào)試。使用此函數(shù)需要dbghelp.h、dbghelp.lib和dbghelp.dll(這些文件可以在Windows Platform SDK中找到)。
要事后根據(jù).dmp文件調(diào)試代碼,需要為發(fā)布版本軟件產(chǎn)生debug symbols (pdb)文件(打開編譯器/DEBUG選項)。在拿到.dmp文件以后,用VC++打開.dmp文件,然后調(diào)試執(zhí)行(按F5鍵)。這樣,崩潰現(xiàn)場就會重現(xiàn)。文獻(xiàn)[5]基于上述的方法實現(xiàn)了崩潰報告系統(tǒng)。

5 結(jié)論
實踐證明,在上述方法和工具支持下的減少軟件內(nèi)存缺陷的方法和工具,可以有效防止和查找代碼中的內(nèi)存錯誤和內(nèi)存泄漏,并且能和開發(fā)人員日常編碼無縫結(jié)合,執(zhí)行起來非常高效。上述方法配合單元測試、代碼評審、每日構(gòu)建、Bug追蹤等措施,形成了一個高效的質(zhì)量保證流程,在我們的大型平臺軟件開發(fā)過程中起到了重要作用

posted on 2011-06-14 14:39 pp_zhang 閱讀(409) 評論(0)  編輯 收藏 引用 所屬分類: c/c++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品网站在线观看| 国产精品va| 一本久道久久综合婷婷鲸鱼| 99国产精品久久久| 亚洲欧美日韩国产中文| 免费日韩av片| 欧美日韩第一页| 国产伦精品一区二区三| 亚洲精品乱码久久久久久蜜桃91| 午夜精品影院| 亚洲激情啪啪| 欧美精品在线免费播放| 欧美在线一区二区| 亚洲国产第一| 欧美一区二区视频97| 欧美人与性动交a欧美精品| 国产精品视频区| 午夜视频久久久| 日韩一级在线| 欧美黄色一区二区| 国产精品久久久久aaaa九色| 亚洲一区二区伦理| 亚洲人线精品午夜| 欧美成人国产| 亚洲精品一区二区三区99| 亚洲激情二区| 欧美黄色片免费观看| 最新国产成人在线观看| 久久久久天天天天| 久久美女性网| 亚洲国产视频一区| 欧美成人免费在线| 亚洲素人在线| 国产日韩精品一区二区| 欧美在线高清| 亚洲嫩草精品久久| 玉米视频成人免费看| 欧美 日韩 国产一区二区在线视频| 久久精品国产第一区二区三区| 国产欧美精品一区aⅴ影院| 老鸭窝91久久精品色噜噜导演| 久久成人18免费网站| 精品成人一区二区| 久久国产99| 久久一区亚洲| 日韩视频国产视频| 艳女tv在线观看国产一区| 国产区日韩欧美| 玖玖视频精品| 欧美国产日韩a欧美在线观看| 国产香蕉久久精品综合网| 久久另类ts人妖一区二区| 久久久久久久97| 亚洲国产婷婷香蕉久久久久久99 | 久久免费黄色| 亚洲人午夜精品免费| 99xxxx成人网| 国产精品久久久久久久久婷婷 | 亚洲全黄一级网站| 亚洲欧洲中文日韩久久av乱码| 欧美不卡一区| 欧美日韩www| 国产精品夜夜夜| 国产精品成人一区二区| 久久久久成人精品| 欧美裸体一区二区三区| 久久久欧美一区二区| 欧美日本久久| 麻豆久久精品| 国产精品毛片va一区二区三区| 免费成人网www| 国产精品国产精品国产专区不蜜| 毛片精品免费在线观看| 国产精品高清网站| 亚洲国产一区二区a毛片| 国产午夜精品视频免费不卡69堂| 亚洲精品在线观看视频| 在线日本欧美| 香蕉成人久久| 亚洲一区日本| 欧美激情自拍| 欧美激情四色| 在线播放中文字幕一区| 亚洲欧美成人一区二区三区| 一区二区三区精品| 欧美成人国产| 欧美成人有码| 亚洲高清视频在线观看| 久久久亚洲人| 久久综合伊人| 国产一区二区在线免费观看| 亚洲一区二区三区乱码aⅴ| 一本色道久久综合亚洲精品高清 | 国产日韩一区二区| 亚洲午夜久久久久久尤物 | 欧美日韩在线视频一区二区| 免费不卡在线观看av| 国产一区二区三区久久精品| 亚洲特色特黄| 亚洲专区国产精品| 欧美系列精品| 一二美女精品欧洲| 亚洲天堂av综合网| 国产精品国产三级国产普通话三级 | 亚洲精品日韩在线| 亚洲美女在线看| 欧美日韩精品国产| 91久久精品国产91久久性色| 亚洲黄页视频免费观看| 欧美成人激情视频| 亚洲精品视频免费观看| 一本色道久久加勒比88综合| 欧美极品在线视频| 亚洲精选久久| 亚洲女优在线| 国产网站欧美日韩免费精品在线观看| 亚洲一区欧美二区| 久久免费视频这里只有精品| 亚洲电影在线播放| 欧美激情免费观看| aa级大片欧美| 欧美一区二区三区免费看| 亚洲人成在线播放| 午夜精品剧场| 黄色综合网站| 男女av一区三区二区色多| 亚洲精品永久免费| 欧美中文字幕视频在线观看| 国产亚洲欧美日韩一区二区| 久久精品国产99| 亚洲国产欧美一区| 亚洲嫩草精品久久| 樱花yy私人影院亚洲| 欧美黑人多人双交| 亚洲一区二区成人在线观看| 久久久国产亚洲精品| 91久久久久久久久| 国产精品欧美日韩| 久久综合久久综合九色| 亚洲精品一区久久久久久| 久久www成人_看片免费不卡| 亚洲国产精品毛片| 国产精品视频xxxx| 免费日韩成人| 亚洲欧美日韩综合| 欧美激情综合| 久久成人国产精品| 99精品免费网| 黑人巨大精品欧美黑白配亚洲| 欧美精品一区二区三区一线天视频| 一区二区日韩免费看| 黄色国产精品| 欧美午夜视频| 欧美h视频在线| 午夜久久电影网| 亚洲美女视频在线免费观看| 久久久久一区二区三区| 亚洲午夜精品17c| 亚洲经典一区| 极品尤物av久久免费看| 欧美人妖在线观看| 久久久久网址| 亚洲欧美激情在线视频| 亚洲黄色精品| 快she精品国产999| 欧美一区网站| 亚洲伊人色欲综合网| 在线观看国产一区二区| 国产免费观看久久| 欧美日韩精品一区二区天天拍小说 | 亚洲国产精品电影| 久久久久九九九九| 午夜精品久久久久久久久久久| 亚洲国产岛国毛片在线| 国产永久精品大片wwwapp| 国产美女精品| 国产精品高清在线观看| 欧美肉体xxxx裸体137大胆| 欧美不卡激情三级在线观看| 久久久久青草大香线综合精品| 先锋亚洲精品| 亚洲一区二区三区久久 | 久久精品国产清高在天天线| 亚洲专区一区| 亚洲一区免费看| 亚洲自拍都市欧美小说| 亚洲午夜黄色| 亚洲欧美国产日韩中文字幕| 亚洲欧美日韩视频一区| 久久国产精品99精品国产| 欧美aa国产视频| 中文精品99久久国产香蕉| 最新国产乱人伦偷精品免费网站| 欧美中文字幕不卡| 欧美电影资源| 久久精品视频免费播放| 亚洲精品中文字幕在线| 亚洲高清视频在线| 91久久久久久国产精品| 欧美精品在线一区二区三区|