專利名稱:程序設計中內存操作錯誤的識別方法
技術領域:
本發明涉及計算機軟件測試技術,具體涉及一種用于檢測程序設計中錯誤內存操作的軟件測試方法,更具體地說,涉及一種C/C++程序設計中內存操作錯誤的識別方法。
作為系統程序設計語言的C/C++是一種高度靈活的語言,也正是這種靈活性為程序的正確編寫帶來極大困難,貌似正確的程序常常因為錯誤的指針和數組操作而導致系統崩潰。國外已有類似的測試工具,如Purify、Visionsoft和Smartheap等,其功能各有側重。Visionsoft和smartheap在檢測錯誤的內存操作方面功能很弱,因為它不能對被測源程序進行有效的插裝。上述測試工具Purify能檢測出不少的內存錯誤操作,但它有一個嚴重缺陷,即它沒有建立內存塊和指針間的關聯,它只能判斷指針的引用是否指向非法內存,而不知道它是否已經指向了另一塊合法內存,這是一個嚴重錯誤。例如,如圖所示,內存塊1和內存塊2是purify所登記的兩塊內存,它們的首址和尺寸分別是(0X1000,4)、(0X1008,8)。現在有一指針p,程序將內存塊1的首址賦給了它,即p指向了內存塊1,現在有一關于指針p的引用*(p+10),它已經越出了內存塊1而到了內存塊2的內部,由于purify認為內存塊2是一塊合法的內存,它不會報告這個錯誤。其根本原因在于purify沒有為指針和內存塊建立關聯,它不知道一個指針應該指向哪一塊內存。
本發明的目的是提出一種新的識別程序設計中內存操作錯誤的方法,它可以針對purify類軟件在指針越界檢查方面存在的上述弱點,不僅能檢測purify類軟件所能檢測的所有錯誤,還能準確地判斷指針的引用是否越出了它所指向的內存塊。對于上例中的指針越界錯,它能很容易地作出判斷。
本發明的目的是這樣實現的,構造一種識別程序設計中內存操作錯誤的方法包括以下步驟由插裝程序對被測試源程序進行分析插裝,對被插裝后被測源程序進行編譯產生可執行的被測程序,運行該可執行程序后產生錯誤日志,最后由錯誤信息瀏覽裝置對錯誤日志信息進行處理,其特征在于所述插裝程序是這樣對被測試源程序進行分析插裝的所述對源程序進行插裝的步驟是基于包含有指針句柄表和顏色表的插裝庫進行的,所述指針句柄表為每個指針項記錄其指針標示和內存塊句柄,所述顏色表為每一個內存塊項記錄內存塊標示、屬性和指向它的指針句柄,所述的對源程序進行插裝的步驟包括打開源程序文件并對每一語句進行分析,分別作如下處理對語句中包含有動態內存、變量和字符串常量的內存塊時,插入登記內存塊的語句;對分析中出現指針賦值語句時,插入登記指針并建立與內存塊間關系的語句;對分析中出現有數組和表達式語句時,插入對數組及表達式進行檢查的語句。
按照本發明提供的方法,其特征在于,所述插入登記內存塊的語句包括對動態內存塊,接管動態內存分配函數,在新的動態內存分配函數中首先調用系統提供的被替換前的分配函數來完成實際的內存分配工作,然后調用插裝庫里的相應函數來登記剛分配的動態內存;對字符串常量,用一函數將被測程序中所出現的字符串常量“包”起來,在“包”它的函數中調用插裝庫中的相應函數來登記這個字符串常量;對變量,記住每一個變量的定義,并且在之后的適當位置插入登記這些變量的語句。
按照本發明提供的方法,其特征在于,所述插入登記指針并建立與內存塊間關系的語句是指在所有找到的為指針賦值的表達式的后面,插入登記指針和建立聯系的語句,如果為指針賦值的表達式中“=”右表達式的最外層最終可歸結為一個指針經過有限次的‘+’、‘-’運算的結果,則將“=”左指針和找到的這個指針指向同一塊內存;否則,用右表達式的值在顏色表中進行匹配,如果它的值落在某一塊內存之中,則認為“=”之左指針指向這塊內存,在不能區分以上兩種情況時,按第二種情況處理。
按照本發明提供的方法,其特征在于,所述插入對數組及表達式進行檢查的語句是指在每一個數組表達式和指針表達式前面,按由內到外的順序逐層檢查,插入相應代碼,以便可根據所述指針句柄表與顏色表,準確地檢查出程序中指針越界和數組越界錯誤操作。
實施本發明提供的程序設計中內存操作錯誤的識別方法,可以有效地檢測出諸如C/C++編程語言所編制程序中的如下一些錯誤1)引用未初始化的指針;2)數組引用越界;3)指針引用越界;4)讀未初始化的動態內存;5)釋放無效的內存塊;6)動態內存分配而未釋放(內存泄漏)。本發明提供的識別方法并不局限于某一產品,也不受運行平臺的限制,是一個通用的測試手段。利用本發明的方法,可以大大提高程序可靠性,改善測試效率和程序質量,并可大大降低在軟件測試方面的開銷。
結合附圖和實施例,進一步說明本發明的特點,附圖中
圖1為用于說明發生內存操作錯誤時的內存組織示意圖;圖2是說明本發明中指針句柄表與顏色表之間關系的示意圖;圖3是利用本發明的方法識別程序設計中內存操作錯誤的整體流程示意圖;圖4是利用本發明的方法進行程序設計中內存操作錯誤識別的插裝程序的流程示意圖;圖5是利用本發明的方法對數組表達式進行識別處理的流程示意圖;圖6是利用本發明的方法對指針表達式進行識別處理的流程示意圖。
為進一步說明本發明的方法,將其中涉及的基本概念說明如下1)插裝對于給定的源程序,按預定的規則插入代碼和改裝程序,這個過程叫插裝。由C/C++語言的特性決定了必須插裝被測源程序才能對它進行比較完善和準確地檢查。
2)插裝庫將同被測程序一起運行的函數庫,它提供了一系列的服務,如登記內存塊、登記指針、指針表達式檢查、數組表達式檢查等。這些服務都是以C函數的形式存在,通過調用這些函數來獲得服務。
3)插裝規范窮盡所有需要插裝的句型,制定相應的插裝規則。這些規則的集合就是插裝規范。每條規則包括兩部分的內容什么情況下需要這種插裝;插裝什么內容。
4)插裝程序按給定插裝規范插裝被測源程序。它具體實現了插裝規范中的每條規則。
5)指針句柄表和顏色表用來明確每個指針所指向的內存塊,以及一塊內存為哪些指針所指的兩張表,它完整的描述了每一指針和內存塊間的關系。這兩張表的結構已定義在插裝庫中,插裝庫還提供相應的服務來操作這兩張表,插裝程序在需要的時候將調用這些服務的語句插入到被測源程序中,被測程序在運行時根據這些語句動態地維護這兩張表。
指針句柄表是指針項的集合,顏色表是內存塊項的集合。如圖2所示,指針句柄表201中的每一項記錄每一個指針的信息,包含有它所指向的內存塊在顏色表中的句柄,上例中指針項1、2、n中的內存塊句柄分別為1、1、2。
顏色表202記錄每一合法內存塊(動態內存、變量、字符串常量)信息,其中包含有指向它的指針在指針句柄表中的句柄,上例中,內存塊項1、2、n中存儲的指向它的指針的句柄分別為{1,2}、{n}、Φ。
內存塊退出作用域時,將在顏色表中找到它所對應的內存塊項,由其所記錄的指向它的指針的句柄,在指針句柄表中找到對應的指針項,將這些指針項中的內存塊句柄置空。
指針標示是一個地址,即指針所在的地址,對一個給定的指針pointer,它的標示為&pointer;內存塊標示也是一個地址,是這塊內存的首址。上例中我們只是簡單的取標示為1,2,......等。
圖3示出了利用本發明的方法識別程序設計中內存操作錯誤的整體流程示意圖。如圖所示,先在方框302中對被測源程序301進行分析并按預定的規則進行插裝,將經過插裝的源程序303在框304由用戶提供的編譯程序進行編譯,形成可執行的被測程序305,并在框306中對可執行的被測程序305進行執行,在執行過程中,產生錯誤日志(框307),最后在框308中調用錯誤信息瀏覽器瀏覽錯誤。由于被測源程序(框301)已插入了利用本發明方法提供的代碼,并按要求進行了改裝(框302),所以能夠動態地跟蹤檢測并瀏覽到原被測程序中存在的內存操作錯誤。
如前所述,本發明的關鍵在于通過插裝代碼,能夠動態地跟蹤被測程序,以檢查程序錯誤。因此插入的內容(稱之為插裝庫)和插裝規范將在實施本發明的方法中顯得尤為重要,也是本發明方法區別于和優于現有技術的關鍵之所在。
只有將調用插裝庫的語句正確插入被測程序,插裝庫才有價值,插裝規范決定了插裝庫的內容,插裝規范是整個方法及其實施的核心。插裝程序嚴格按照插裝規范分析并插裝被測程序,它所插入的內容是調用插裝庫所提供的服務的語句。插入的語句在被測程序運行時會完成這樣兩大部分的工作維持指針句柄表和顏色表以及它們之間的關系;對指針表達式和數組表達式進行檢查。圖4示出了利用本發明的方法進行程序設計中內存操作錯誤識別的插裝程序的流程。如圖4所示,在進行的準備操作401后,在框402打開被測源程序文件,在判定框403中判定是否文件結束,如是文件結束,則轉到結束框409,如不是文件結束,則在框404中從被測源程序中讀一語句到緩沖區S,再在分析框405中對S中內容進行分析,并分別不同情況進行相應處理,如分析出是動態內存、變量和字符串常量,則在框406中進行插入登記內存塊的語句的操作;如分析出程序中出現指針賦值語句,則在框407中進行插入登記指針并建立與內存塊間關系的語句的操作;如分析出語句中包含數組表達式或指針表達式語句,則在框408中插入對數組和指針表達式進行檢查的語句;在完成框406、407和408中的操作后,重新轉到框403進行是否為文件結束的判定,如此循環,直到讀到文件結束,程序終止于框409。
下面結合圖4中的三個主要處理過程插入登記內存塊的語句(框406),插入登記指針并建立它與內存塊間關系的語句(框407);插入對數組和指針表達式進行檢查的語句(框408),進一步說明本發明的方法中所采用的插裝規范。<1>插入登記內存塊的語句此處只考慮登記這樣幾類內存塊動態內存、變量和字符串常量。分別描述如下動態內存塊的登記規范接管動態內存分配函數,在新的動態內存分配函數中首先調用系統提供的被替換前的分配函數來完成實際的內存分配工作,然后調用插裝庫里的相應函數來登記剛分配的動態內存。
字符串常量登記規范用一函數將被測程序中所出現的字符串常量“包”起來,在“包”它的函數中調用插裝庫中的相應函數來登記這個字符串常量。
變量登記規范記住每一個變量的定義,并且在之后的適當位置插入登記這些變量的語句。適當的位置示被測程序是C還是C++而定,對于C程序,將在這塊語句中所有變量定義之后和第一條非變量定義語句之前插入登記這些變量的代碼;對于C++程序,可以在緊跟著變量的定義之后插入代碼來登記這些變量。<2>插入登記指針并建立它與內存塊間關系的語句本發明的方法只有在分析出程序包含有指針賦值語句時才登記該指針,登記指針的同時也就把顏色表中的某些內存塊和這個指針聯系起來了。具體地,將找到所有的為指針賦值的表達式,在之后插入登記指針和建立聯系的語句。
在為指針和內存塊建立聯系時,我們采取了這樣一種策略。即找到每一為指針賦值的表達式,根據“=”右表達式的結構,將其區分為兩種情況,分別作不同的處理。如果右表達式的最外層最終可歸結為一個指針經過有限次的‘+’、‘-’運算的結果,我們將認為“=”左指針和找到的這個指針指向同一塊內存。否則,我們將用右表達式的值在顏色表中進行匹配,如果它的值落在某一塊內存之中,則認為“=”之左指針指向這塊內存。在不能區分以上兩種情況時,我們將按第二種情況處理。<3>插入對數組和指針表達式進行檢查的語句指針表達式和數組表達式總可表達為這樣兩種形式p[exprl][expr2]…[exprn]及*(…*(*(p+expr1)+expr2)+exprn)。其中expr1,expr2,…exprn又可能是指針表達式或數組表達式,這是嵌套的表示。
本發明的方法對于被測程序中出現的每一個數組表達式和指針表達式,都將在它的前面,按由內到外的順序,插入相應代碼,一層一層的檢查。
一旦插裝程序將相應的檢測語句插入到被測程序中,當被測程序運行時,這些語句將根據指針句柄表與顏色表,準確地檢查出程序中錯誤的內存操作,錯誤的內存操主要包括指針越界和數組越界。
下面討論插入的這些語句是如何對數組表達式和指針表達式進行檢查的。
圖5示出了對數組表達式進行識別處理的具體流程。對數組表達式檢查是這樣進行的,如圖5所示,插裝庫在收到對數組表達式進行檢查的請求后,首先在框501中進行準備,在框502中進行id和addr的賦值,在框503把數組的地址作為關鍵字在顏色表中進行查找,在框504中進行判定,如找到內存塊,則進到框505,根據內存塊屬性(首址、尺寸)在框506中判斷判斷這個數組引用addr是否越界,如越界就在框507記錄錯誤信息,如沒有越界,則進到結束框508。
圖6示出了對指針表達式進行識別處理的流程。如圖6所示,插裝庫在收到對指針表達式進行檢查的請求后,從開始框601開始,在框602中對id和addr進行賦值,然后在框603中,把指針地址id作為關鍵字,在指針句柄表中查找其對應項pointer,在框604中判定是否找到,如未找到,則進到框609,記錄錯誤信息;如已找到,則在框605中,以框603中找到的poniter作為內存塊句柄,查找顏色表中對應的內存塊項mem,在框606中,如未找到內存開項,則進到框609,記錄錯誤信息;如已找到,則在框607,根據此內存塊項中存儲的內存塊屬性(首址、尺寸等)來判斷這個指針表達式是否越界,如在框608中判定是發生越界,則進到框609,記錄錯誤信息;如未發生越界,則進到結束框610,在框609記錄完錯誤信息后,也轉到結束框610。<4>其它規范對于特定的句型,如while、do-while、for、switch等語句,插裝規范將對它進行改裝,以滿足我們上述登記和檢查的需要。
作為附帶工作,可以插入代碼完成諸如讀未初始化的動態內存、釋放無效的內存塊、動態內存分配而未釋放等檢查。
最后介紹本發明方法的一個具體的實施案例利用本發明的方法構造的測試工具Clearify是一個與產品和運行平臺無關的測試工具,只要求所在平臺提供標準C/C++編譯器即可。利用該測試工具Clearify我們對一個用C/C++編程的大型交換機軟件進行的內存操作錯誤的識別,其使用方法如下將被測軟件(或模塊)的makefile文件中的宏CC更改為CC=clearify hc386 hc386,執行命令make編譯被測軟件,將得到的可執行程序輸入到主機或仿真環境中,運行,最后調用Clearify提供的錯誤信息瀏覽器定位錯誤。通常,在C/C++程序中,內存操作錯誤在所有可能的錯誤中占有最大比重,尤其是對于數十萬行的大型軟件。一個可以預見的效果是交換機將因此而運行得更加穩定,至少我們可以排除這種錯誤。
權利要求
1.一種識別程序設計中內存操作錯誤的方法,包括以下步驟對源程序進行插裝,編譯并運行插裝后的程序,從運行產生的錯誤日志取得出錯信息,其特征在于所述對源程序進行插裝的步驟是基于包含有指針句柄表和顏色表的插裝庫進行的,所述指針句柄表為每個指針項記錄其指針標示和內存塊句柄,所述顏色表為每一個內存塊項記錄內存塊標示、屬性和指向它的指針句柄,所述的對源程序進行插裝的步驟包括打開源程序文件并對每一語句進行分析,分別作如下處理對語句中包含有動態內存、變量和字符串常量的內存塊時,插入登記內存塊的語句;對分析中出現指針賦值語句時,插入登記指針并建立與內存塊間關系的語句;對分析中出現有數組和表達式語句時,插入對數組及表達式進行檢查的語句。
2.根據權利要求1所述的方法,其特征在于,所述插入登記內存塊的語句包括對動態內存塊,接管動態內存分配函數,在新的動態內存分配函數中首先調用系統提供的被替換前的分配函數來完成實際的內存分配工作,然后調用插裝庫里的相應函數來登記剛分配的動態內存;對字符串常量,用一函數將被測程序中所出現的字符串常量“包”起來,在“包”它的函數中調用插裝庫中的相應函數來登記這個字符串常量;對變量,記住每一個變量的定義,并且在之后的適當位置插入登記這些變量的語句。
3.根據權利要求1所述的方法,其特征在于,所述插入登記指針并建立與內存塊間關系的語句是指在所有找到的為指針賦值的表達式的后面,插入登記指針和建立聯系的語句,如果為指針賦值的表達式中“=”右表達式的最外層最終可歸結為一個指針經過有限次的‘+’、‘-’運算的結果,則將“=”左指針和找到的這個指針指向同一塊內存;否則,用右表達式的值在顏色表中進行匹配,如果它的值落在某一塊內存之中,則認為“=”之左指針指向這塊內存,在不能區分以上兩種情況時,按第二種情況處理。
4.根據權利要求1所述的方法,其特征在于,所述插入對數組及表達式進行檢查的語句是指在每一個數組表達式和指針表達式前面,按由內到外的順序逐層檢查,插入相應代碼,以便可根據所述指針句柄表與顏色表,準確地檢查出程序中指針越界和數組越界錯誤操作。
全文摘要
一種識別程序設計中內存操作錯誤的方法,對源程序的插裝是基于包含有指針句柄表和顏色表的插裝庫進行的,對語句中包含有動態內存、變量和字符串常量的內存塊時,插入登記內存塊的語句;對指針賦值語句,插入登記指針并建立與內存塊間關系的語句;對數組和表達式語句,插入對數組及表達式進行檢查的語句。利用該方法可有效地檢測出內存操作有關的編程錯誤,提高測試效率和程序質量,降低測試方面的費用開銷。
文檔編號G06F11/00GK1188933SQ98104528
公開日1998年7月29日 申請日期1998年2月6日 優先權日1998年2月6日
發明者陳青, 劉運渠, 肖華熙, 龍晶 申請人:深圳市華為技術有限公司