亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        C++內(nèi)存檢測的研究

        2014-07-04 01:42:46楊英豪孫永超
        電子工業(yè)專用設(shè)備 2014年12期
        關(guān)鍵詞:堆棧指針調(diào)用

        柳 青,楊英豪,孫永超

        (中國電子科技集團公司第四十五研究所,北京101601)

        隨著計算機在各個領(lǐng)域內(nèi)的廣泛應(yīng)用,IT 行業(yè)得到突飛猛進的發(fā)展。但程序畢竟是由人的思想產(chǎn)生,所以總會存在一些隱患。內(nèi)存泄漏就是一個常見的問題,其隱蔽性讓人不易察覺;如何找到并解決內(nèi)存泄漏成為程序設(shè)計中的關(guān)鍵。

        1 程序的存放及組織方式

        在計算機里程序通常以進程的方式運行,而任何的進程都需要開辟內(nèi)存,內(nèi)存就是存放數(shù)據(jù)的介質(zhì)。程序員在編寫程序時都會和內(nèi)存打交道,常用的有數(shù)組、類等。數(shù)組和普通變量一樣可以被聲明為靜態(tài)或動態(tài)的;靜態(tài)數(shù)組在程序加載時定位于數(shù)據(jù)段;動態(tài)數(shù)組在程序運行時定位于堆棧之中。

        1.1 進程在內(nèi)存中的組織形式

        一般進程由3 個部分組成:文本區(qū)域,數(shù)據(jù)區(qū)域和堆棧區(qū)域。如圖1所示。

        文本區(qū)域由程序本身自己確定,它包括代碼和數(shù)據(jù)。這個區(qū)域通常是只讀的,任何對它的寫操作都會導(dǎo)致段錯誤。

        數(shù)據(jù)區(qū)域包括初始化和未初始化的數(shù)據(jù)。bss段用來存放未初始化的數(shù)據(jù),data 段用來存放以初始化的數(shù)據(jù)。從C 語言的角度來說數(shù)據(jù)區(qū)域主要用來存放靜態(tài)變量。

        圖1 內(nèi)存的組織形式

        堆棧在高級語言中起到很大的作用,高級語言主要是面向過程和函數(shù)的,當(dāng)一個過程調(diào)用完可以用簡單的跳轉(zhuǎn)指令;因函數(shù)之間可以嵌套調(diào)用,這樣使得程序的邏輯很簡單,但調(diào)用之后釋放控制權(quán)就不能用簡單的跳轉(zhuǎn)指令,這時就必須使用堆棧了。

        1.2 堆棧定義

        堆棧是一種抽象的數(shù)據(jù)類型,堆棧的顯著特性是后進先出(LIFO)。堆棧定義了兩種操作進棧(PUSH)和出棧(POP)。進棧時操作是從堆棧頂部加入一個元素;出棧操作是從堆棧頂部減去一個元素。

        堆棧既可以向下增長(向內(nèi)存低地址)也可以向上增長,這依賴于具體的實現(xiàn)。此外有一個指針始終指向堆棧稱為堆棧指針(SP),它也是依賴于具體實現(xiàn)的;它可以指向堆棧的最后地址,或者指向堆棧之后的下一個空閑可用地址。在我們的討論當(dāng)中,SP 指向堆棧的最后地址。

        除了堆棧指針(SP 指向堆棧頂部的低地址)之外,為了使用方便還有指向棧內(nèi)固定地址的指針叫做幀指針(FP),或者局部基指針(LB-local base pointer)。從理論上來說,局部變量可以用SP 加偏移量來引用。然而,當(dāng)有字被壓棧和出棧后,這些偏移量就變了。盡管在某些情況下編譯器能夠跟蹤棧中的字操作,由此可以修正偏移量,但是在某些情況下是不能的;而且在所有情況下,要引入可觀的管理開銷。

        因此,許多編譯器使用第二個寄存器存放FP,對于局部變量和函數(shù)參數(shù)都可以引用,因為它們到FP 的距離不會受到壓棧和出棧操作的影響。

        2 內(nèi)存泄漏

        內(nèi)存泄漏(memory leak)指由于疏忽或錯誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并非指內(nèi)存在物理上的消失,而是應(yīng)用程序在分配某段內(nèi)存后,由于設(shè)計錯誤,在程序使用完這段內(nèi)存時,未能釋放給操作系統(tǒng),從而失去了對該段內(nèi)存的控制,因此造成了內(nèi)存的浪費。

        內(nèi)存泄漏的分類:

        (1)常發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼會被多次執(zhí)行到,每次被執(zhí)行的時候都會導(dǎo)致一塊內(nèi)存泄漏。

        (2)偶發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會發(fā)生。常發(fā)性和偶發(fā)性是相對的。對于特定的環(huán)境,偶發(fā)性的也許就變成了常發(fā)性的。所以測試環(huán)境和測試方法對檢測內(nèi)存泄漏至關(guān)重要。

        (3)一次性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只會被執(zhí)行一次,或者由于算法上的缺陷,總會導(dǎo)致且僅有一塊內(nèi)存發(fā)生泄漏。比如,在一個類的構(gòu)造函數(shù)中分配內(nèi)存,但在析構(gòu)函數(shù)中卻沒有釋放該內(nèi)存。而該類只存在一個實例,所以內(nèi)存泄漏只會發(fā)生一次。

        (4)隱式內(nèi)存泄漏。程序在運行過程中不停的分配內(nèi)存,但是直到結(jié)束的時候才釋放內(nèi)存。嚴(yán)格的說這里并沒有發(fā)生內(nèi)存泄漏,因為最終程序釋放了所有申請的內(nèi)存。但是對于一個服務(wù)器程序,需要運行幾天,幾周甚至幾個月,不及時釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存。所以,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏。

        在高級語言編程中,易造成內(nèi)存泄漏的情況通常是動態(tài)分配的堆棧,即程序動態(tài)申請內(nèi)存,使用完后,未釋放給堆棧。下面是高級語言中幾種動態(tài)深淺堆棧的函數(shù)。

        (1)void *malloc(size_t size)

        此函數(shù)在堆棧中動態(tài)分配一塊size 大小的內(nèi)存。

        void free(void *memblock)

        此函數(shù)與malloc 對應(yīng)的函數(shù),用來釋放其分配的內(nèi)存。

        (2)new [placement]type-name [initializer]

        此函數(shù)是用于在堆棧動態(tài)分配一塊type-name 大小的內(nèi)存,type-name 可以是類也可以是數(shù)組等類型。

        delete [pointer]

        此函數(shù)與new 是對應(yīng)的函數(shù),用來釋放其分配的內(nèi)存。

        此外還有一些標(biāo)準(zhǔn)函數(shù)在使用不當(dāng)時也會造成溢出。包括strcat(),strcpy(),sprintf(),vsprintf()。這些函數(shù)對一個NULL 結(jié)尾的字符串進行操作,并不檢查溢出情況。gets()函數(shù)從標(biāo)準(zhǔn)輸入中讀取一行到緩沖區(qū)中,直到換行或EOF,它也不檢查緩沖區(qū)溢出。scanf()函數(shù)族在匹配一系列非空格字符(%s),或從指定集合(%[])中匹配非空字符時,使用字符指針指向數(shù)組,并且沒有定義最大字段寬度這個可選項,就可能出現(xiàn)問題.如果這些函數(shù)的目標(biāo)地址是一個固定大小的緩沖區(qū),函數(shù)的另外參數(shù)是由用戶以某種形式輸入,則很有可能利用緩沖區(qū)溢出來破解它。

        3 內(nèi)存泄漏檢測

        3.1 使用標(biāo)準(zhǔn)庫函數(shù)檢測內(nèi)存泄漏

        Visual Studio 調(diào)試器和C 運行時(CRT) 庫中為我們提供了一些檢測和識別內(nèi)存泄漏的有效方法。如調(diào)試堆棧函數(shù)和輸入調(diào)試信息等函數(shù)。但默認(rèn)總是關(guān)閉的,所以我們要手動打開。

        分以下兩個步驟:

        (1)使用調(diào)試堆棧函數(shù)

        #include

        #include

        #define _CRTDBG_MAP_ALLOC

        (2)輸出內(nèi)存泄漏信息

        _CrtDumpMemoryLeaks();在需要檢測內(nèi)存泄漏的地方添加此函數(shù)用來輸出內(nèi)存泄漏的信息。如圖2所示。

        圖2 使用C 標(biāo)準(zhǔn)函數(shù)輸出內(nèi)存泄漏信息

        我們可以得到內(nèi)存泄漏的地址和內(nèi)存泄漏的內(nèi)容,但我們無法知道內(nèi)存泄漏的具體函數(shù)。

        3.2 使用Visual Leak Detector 檢測內(nèi)存泄漏

        Visual Leak Detector 是一款用于Visual C++的免費內(nèi)存泄露檢測工具。它在每次內(nèi)存分配時將其上下文記錄下來,當(dāng)程序退出時,對于檢測到的內(nèi)存泄漏,查找其記錄下來的上下文信息,并將其轉(zhuǎn)換成報告輸出。

        相比較其它的內(nèi)存泄露檢測工具,它在檢測到內(nèi)存泄漏的同時,還具有如下特點:

        (1)可以得到內(nèi)存泄漏點的調(diào)用堆棧,如果可以的話,還可以得到其所在文件及行號;

        (2)可以得到泄露內(nèi)存的完整數(shù)據(jù);

        (3)可以設(shè)置內(nèi)存泄露報告的級別;

        (4)它是一個已經(jīng)打包的lib,使用時無須編譯它的源代碼。而對于使用者自己的代碼,也只需要做很小的改動;

        (5)它的源代碼使用GNU 許可發(fā)布,并有詳盡的文檔及注釋。對于想深入了解堆內(nèi)存管理的讀者,是一個不錯的選擇。

        在http://www.codeproject.com/KB/applications/visualleakdetector.aspx 可以下載到 Visual Leak Detector 的源碼,編譯后安裝;或直接下載安裝包進行安裝。如圖3所示:

        安裝完成后,我們還有配置一些選項才能使用Visual Leak Detector。

        (1)拷貝Visual Leak Detector 的lib 文件至Visual C++安裝目錄下的lib 子文件夾內(nèi)

        (2)拷貝Visual Leak Detector 頭文件(vld.h and vldapi.h)至Visual C++ 安裝目錄下的“include”子文件夾

        圖3 安裝Visual Leak Detector

        (3)在程序入口點所在的源文件內(nèi)包含vld.h。最好將此頭文件包含在其他頭文件之前,stdafx.h 之后,但這并不是必須的。如果這個源文件包含了stdafx.h,那么vld.h 應(yīng)該在其后包含。

        (4)如果運行環(huán)境是windows2000 或更新,則需要拷貝dbghelp.dll 至被調(diào)試的可執(zhí)行文件目錄下。

        編譯測試程序運行,我們可以得到內(nèi)存泄漏的詳細(xì)信息,內(nèi)存泄漏的地址,函數(shù)調(diào)用的堆棧及泄漏內(nèi)存的內(nèi)容,如圖4所示。

        圖中第二行表示56 號塊有4 字節(jié)的內(nèi)存泄漏,地址為0x003F3ED8。我們可以看到堆棧調(diào)用的結(jié)果,第四行表示運行到程序的第12 行的f()函數(shù)里產(chǎn)生內(nèi)存泄漏;在該地址處分配了4 字節(jié)的堆內(nèi)存空間,并賦值為0x12345678;在第九行我們看到了這4 字節(jié)同樣的內(nèi)容,即內(nèi)存泄漏的堆棧數(shù)據(jù)。

        圖4 使用Visual Leak Detector 檢測內(nèi)存泄漏

        可以看出,對于每一個內(nèi)存泄漏,這個報告列出了它的泄漏點、長度、分配該內(nèi)存時的調(diào)用堆棧和泄露內(nèi)存的內(nèi)容(分別以16 進制和文本格式列出)。雙擊該堆棧報告的某一行,會自動在代碼編輯器中跳到其所指文件的對應(yīng)行。這些信息對于我們查找內(nèi)存泄露將有很大的幫助。

        4 結(jié)束語

        綜上所述內(nèi)存泄漏有一定的隱蔽性,所以給我們查找?guī)砹艘恍╇y度。盡管C++提供了標(biāo)準(zhǔn)的庫函數(shù)用來檢測內(nèi)存泄漏,但它不能產(chǎn)生具體的堆棧調(diào)用結(jié)果。而Visual Leak Detector 不但使用簡單,也能報告堆棧調(diào)用的詳細(xì)結(jié)果,使內(nèi)存使用情況一目了然,為我們檢測內(nèi)存泄漏提供了方便可靠的方法。

        [1]孫鑫.VC++ 深入詳解[M].北京:電子工業(yè)出版社,2008.

        [2]林銳.高質(zhì)量C++編程指南[Z].2001.

        猜你喜歡
        堆棧指針調(diào)用
        核電項目物項調(diào)用管理的應(yīng)用研究
        偷指針的人
        娃娃畫報(2019年5期)2019-06-17 16:58:10
        LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
        嵌入式軟件堆棧溢出的動態(tài)檢測方案設(shè)計*
        為什么表的指針都按照順時針方向轉(zhuǎn)動
        基于堆棧自編碼降維的武器裝備體系效能預(yù)測
        基于系統(tǒng)調(diào)用的惡意軟件檢測技術(shù)研究
        基于改進Hough變換和BP網(wǎng)絡(luò)的指針儀表識別
        電測與儀表(2015年5期)2015-04-09 11:30:42
        ARM Cortex—MO/MO+單片機的指針變量替換方法
        利用RFC技術(shù)實現(xiàn)SAP系統(tǒng)接口通信
        亚洲gv白嫩小受在线观看| 窝窝午夜看片| 专干老肥熟女视频网站300部| 日本一卡2卡3卡四卡精品网站| 波多野吉衣av无码| 国产一毛片| 亚洲 欧美精品suv| 欧美在线综合| 官网A级毛片| 中文字幕亚洲精品一二三区| 日本视频一区二区三区在线| 四虎永久在线精品免费一区二区 | 国产在线精品一区二区三区不卡| 欧美亚洲国产另类在线观看| 国产亚洲精品性爱视频| 精品国产车一区二区三区| 在线中文字幕一区二区| 80s国产成年女人毛片| 久久香蕉国产线看观看精品yw| 扒开双腿疯狂进出爽爽爽视频| 在线视频你懂的国产福利| 日韩在线手机专区av| 女主播啪啪大秀免费观看| 国产精品一区二区三久久不卡| 无码字幕av一区二区三区| 国产在线精品欧美日韩电影| 中文字幕第1页中文字幕在| av网址大全在线播放| 粉嫩人妻91精品视色在线看| 国产成人精品免费久久久久| 色妞ww精品视频7777| 久久99精品国产99久久| 亚洲无码啊啊啊免费体验| 国产精品女同一区二区免| 在线精品国产亚洲av蜜桃| 97久久综合区小说区图片区| 99精品国产综合久久久久五月天| 91精品国产综合久久青草| 久久亚洲一区二区三区四区五| 亚洲av毛片在线免费观看| 97日日碰曰曰摸日日澡|