本發(fā)明涉及計算機領域,具體而言,涉及一種堆內(nèi)存操作的檢測方法及裝置。
背景技術:
在應用軟件運行的過程中,會存在對應用軟件的堆內(nèi)存進行非法操作,該非法操作一般為如下幾種:堆內(nèi)存塊越界讀寫、讀寫未分配的堆內(nèi)存、讀寫已經(jīng)釋放的堆內(nèi)存、重復釋放堆內(nèi)存、釋放錯誤的堆內(nèi)存地址等。上述非法操作一直都是軟件開發(fā)過程中最易發(fā)、危害最大又最難解決的問題之一,目前解決上述非法操作的方法是采用C/C++堆內(nèi)存非法訪問動態(tài)檢測工具。
這里需要說明的是,目前普遍存在的C/C++堆內(nèi)存非法訪問動態(tài)檢測工具存在三個缺陷:第一、能檢測的非法操作類型少;第二、檢測工具本身額外內(nèi)存開銷大,導致在許多軟件特別是嵌入式軟件上無法正常運行;第三、檢測工具檢測效率低下,在性能要求較高特別是并發(fā)較激烈的軟件中無法正常運行。
技術實現(xiàn)要素:
本發(fā)明提供了一種堆內(nèi)存操作的檢測方法及裝置,以至少解決相關技術中現(xiàn)有的堆內(nèi)存非法操作檢測工具檢測效率低的問題。
根據(jù)本發(fā)明的一個方面,提供了一種堆內(nèi)存操作的檢測方法,包括:確定對堆內(nèi)存進行操作的操作類型;獲取用于表述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息;依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測。
在本發(fā)明實施例中,在內(nèi)存結(jié)構(gòu)信息包括堆內(nèi)存所包括的內(nèi)存塊的狀態(tài)信息的情況下,依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測包括:確定操作在堆內(nèi)存所對應的內(nèi)存塊;依據(jù)內(nèi)存塊的狀態(tài)信息確定內(nèi)存塊的狀態(tài);依據(jù)操作類型,以及確定的內(nèi)存塊的狀態(tài),判定操作的合法性。
在本發(fā)明實施例中,依據(jù)操作類型,以及確定的內(nèi)存塊的狀態(tài),判定操作的合法性包括以下至少之一:在操作類型為對內(nèi)存塊進行訪問,且內(nèi)存塊的狀態(tài)為已釋放的情況下,判定操作為訪問已釋放內(nèi)存塊的非法操作;在操作類型為對內(nèi)存塊進行讀操作,且內(nèi)存塊的初始化狀態(tài)為未初始化的情況下,判定操作為讀未初始化內(nèi)存塊的非法操作;在操作類型為對內(nèi)存塊進行釋放,且內(nèi)存塊的狀態(tài)為已釋放的情況下,判定操作為重復釋放內(nèi)存塊的非法操作。
在本發(fā)明實施例中,在內(nèi)存結(jié)構(gòu)信息包括堆內(nèi)存所包括的內(nèi)存塊的屬性信息的情況下,依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測的步驟包括:確定操作在堆內(nèi)存塊中的操作范圍;依據(jù)操作范圍,以及內(nèi)存塊的屬性信息判定操作的合法性,其中,內(nèi)存塊的屬性信息包括:操作在堆內(nèi)存中對應的內(nèi)存塊的起始地址以及內(nèi)存塊的使用長度。
在本發(fā)明實施例中,依據(jù)操作范圍,以及內(nèi)存塊的屬性信息判定操作的合法性的步驟包括:判斷操作范圍是否在內(nèi)存塊的起始地址和內(nèi)存塊的使用長度確定的范圍內(nèi);在判斷結(jié)果為否的情況下,確定操作為越界非法操作。
在本發(fā)明實施例中,在內(nèi)存結(jié)構(gòu)信息包括堆內(nèi)存所包括的內(nèi)存塊的屬性信息的情況下,依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測的步驟包括:在操作為釋放操作的情況下,確定操作的釋放地址;在內(nèi)存結(jié)構(gòu)信息中獲取不到釋放地址對應的屬性信息的情況下,判定操作為釋放非內(nèi)存地址的非法操作。
根據(jù)本發(fā)明的另一方面,提供了一種堆內(nèi)存操作的檢測裝置,包括:確定模塊,用于確定對堆內(nèi)存進行操作的操作類型;獲取模塊,用于獲取用于表述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息;檢測模塊,用于依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測。
在本發(fā)明實施例中,檢測模塊還包括,第一確定單元,用于確定操作在堆內(nèi)存所對應的內(nèi)存塊;第二確定單元,用于依據(jù)內(nèi)存塊的狀態(tài)信息確定內(nèi)存塊的狀態(tài);第一判斷單元,用于依據(jù)操作類型,以及確定的內(nèi)存塊的狀態(tài),判定操作的合法性。
在本發(fā)明實施例中,第一判斷單元包括至少如下子單元之一:第一判斷子單元,用于在操作類型為對內(nèi)存塊進行訪問,且內(nèi)存塊的狀態(tài)為已釋放的情況下,判定操作為訪問已釋放內(nèi)存塊的非法操作;第二判斷子單元,用于在操作類型為對內(nèi)存塊進行讀操作,且內(nèi)存塊的初始化狀態(tài)為未初始化的情況下,判定操作為讀未初始化內(nèi)存塊的非法操作;第三判斷子單元,用于在操作類型為對內(nèi)存塊進行釋放,且內(nèi)存塊的狀態(tài)為已釋放的情況下,判定操作為重復釋放內(nèi)存塊的非法操作。
在本發(fā)明實施例中,第三確定單元,用于確定操作在堆內(nèi)存塊中的操作范圍;第二判斷單元,用于依據(jù)操作范圍,以及內(nèi)存塊的屬性信息判定操作的合法性,其中,內(nèi)存塊的屬性信息包括:操作在堆內(nèi)存中對應的內(nèi)存塊的起始地址以及內(nèi)存塊的使用長度。
在本發(fā)明實施例中,第二判斷單元包括:第四判斷子單元,用于判斷操作范圍是否在內(nèi)存塊的起始地址和內(nèi)存塊的使用長度確定的范圍內(nèi);第一確定子單元,用于在判斷結(jié)果為否的情況下,確定操作為越界非法操作。
在本發(fā)明實施例中,檢測模塊還包括:第二確定子單元,用于在操作為釋放操作的情況下,確定操作的釋放地址;第五判斷子單元,用于在內(nèi)存結(jié)構(gòu)信息中獲取不到釋放地址對應的屬性信息的情況下,判定操作為釋放非堆內(nèi)存地址的非法操作。
通過本發(fā)明,采用確定對堆內(nèi)存進行操作的操作類型;獲取用于表述堆內(nèi)存的內(nèi)存 結(jié)構(gòu)信息;依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測,解決了相關技術中現(xiàn)有的堆內(nèi)存非法操作檢測工具檢測效率低的問題,進而達到了提高檢測堆內(nèi)存操作的效率的效果。
附圖說明
此處所說明的附圖用來提供對本發(fā)明的進一步理解,構(gòu)成本申請的一部分,本發(fā)明的示意性實施例及其說明用于解釋本發(fā)明,并不構(gòu)成對本發(fā)明的不當限定。在附圖中:
圖1是根據(jù)本發(fā)明實施例的堆內(nèi)存操作的檢測方法的流程圖;
圖2是根據(jù)本發(fā)明實施例的堆內(nèi)存操作的檢測方法中的內(nèi)存域的示意圖;
圖3是根據(jù)本發(fā)明實施例的可選地堆內(nèi)存操作的檢測方法的流程圖;
圖4是根據(jù)本發(fā)明實施例的可選地堆內(nèi)存操作的檢測方法的流程圖;以及
圖5是根據(jù)本發(fā)明實施例的堆內(nèi)存操作的檢測裝置的結(jié)構(gòu)框圖。
具體實施方式
下文中將參考附圖并結(jié)合實施例來詳細說明本發(fā)明。需要說明的是,在不沖突的情況下,本申請中的實施例及實施例中的特征可以相互組合。
需要說明的是,本發(fā)明的說明書和權(quán)利要求書及上述附圖中的術語“第一”、“第二”等是用于區(qū)別類似的對象,而不必用于描述特定的順序或先后次序。
在本實施例中提供了一種堆內(nèi)存操作的檢測方法,圖1是根據(jù)本發(fā)明實施例的堆內(nèi)存操作的檢測方法的流程圖,如圖1所示,該流程包括如下步驟:
步驟S102,確定對堆內(nèi)存進行操作的操作類型。
具體的,上述操作類型可以為訪問操作,也可以為釋放操作。
這里需要說明的是,上述堆內(nèi)存可以為一個堆內(nèi)存區(qū)域,在上述堆內(nèi)存區(qū)域中可以劃分多個長度相同的內(nèi)存塊,對堆內(nèi)存的操作即為對上述堆內(nèi)存區(qū)域的操作,也即對內(nèi)存塊的操作。
步驟S104,獲取用于表述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息。
具體的,可以通過編譯插樁機制提供的堆內(nèi)存的地址獲取到用于表述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息,上述內(nèi)存結(jié)構(gòu)信息可以分為兩部分,第一部分信息可以為內(nèi)存塊的狀態(tài)信息,比如空閑狀態(tài)、被使用狀態(tài)、釋放狀態(tài)等。第二部分信息可以為內(nèi)存塊的屬性信息,比如內(nèi)存塊的使用長度,內(nèi)存塊的起始地址等。
步驟S106,依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測。
具體的,在本方案中,可以根據(jù)針對操作類型結(jié)合與該堆內(nèi)存對應的結(jié)構(gòu)信息來對上述操作進行檢測,即確定上述針對堆內(nèi)存的操作是合法或違法。
上述步驟中,通過先獲取堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息,然后結(jié)合針對堆內(nèi)存操作的操作類型和上述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息檢測上述操作的合法性,與相關檢測工具相比,極大的降低檢測過程中對內(nèi)存的消耗,并且在并發(fā)運行激烈的軟件中也可以高效率的實現(xiàn)對堆內(nèi)存操作的檢測,從而解決了現(xiàn)有的堆內(nèi)存非法操作檢測工具檢測效率低的問題。
可選地,上述堆內(nèi)存可以包括至少一個內(nèi)存塊,上述內(nèi)存結(jié)構(gòu)信息可以為內(nèi)存塊的狀態(tài)信息,上述步驟S106,依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測的步驟可以包括:
步驟S1061,確定操作在堆內(nèi)存所對應的內(nèi)存塊。
步驟S1062,依據(jù)內(nèi)存塊的狀態(tài)信息確定內(nèi)存塊的狀態(tài)。
步驟S1063,依據(jù)操作類型,以及確定的內(nèi)存塊的狀態(tài),判定操作的合法性。
具體的,可以通過堆內(nèi)存地址來獲取堆內(nèi)存地址所對應的內(nèi)存塊,即操作對象,在上述內(nèi)存塊的尾部可以保存有內(nèi)存塊的狀態(tài)信息,再結(jié)合上述操作類型和上述內(nèi)存塊的狀態(tài)判定操作是否合法。
可選地,上述堆內(nèi)存可以為一個內(nèi)存域,該內(nèi)存域可以包括多個內(nèi)存塊,內(nèi)存塊的狀態(tài)可以記錄在內(nèi)存塊的關鍵信息中。
在一種可選的實施例中,以上述堆內(nèi)存可以由包含多個內(nèi)存塊的內(nèi)存域組成為例,提供一種根據(jù)堆內(nèi)存地址來獲取內(nèi)存塊的關鍵信息的方法:
可以首先先獲取堆內(nèi)存地址Ptr,再根據(jù)堆內(nèi)存地址Ptr通過預先定義好的映射關系去獲取上述堆內(nèi)存地址Ptr所對應的內(nèi)存區(qū)域管理結(jié)構(gòu),在該內(nèi)存區(qū)域管理結(jié)構(gòu)中則記錄著內(nèi)存區(qū)域的起始地址P0和內(nèi)存塊長度Sb,然后根據(jù)堆內(nèi)存地址Ptr、內(nèi)存區(qū)域的起始地址P0和內(nèi)存塊長度Sb得到上述關鍵信息:根據(jù)公式計算出Ptr對應的內(nèi)存塊的起始地址Pb,通過內(nèi)存塊的起始地址Pb加上Sb再減去內(nèi)存塊關鍵信息的大小Si,即可獲得該內(nèi)存塊關鍵信息的起始地址。這里需要說明的是,在上述內(nèi)存塊的關鍵信息可以記錄著上述內(nèi)存塊狀態(tài),比如空閑狀態(tài)FREED,已使用狀態(tài)USED,已初始化或未初始化。
在一種可選的實施例中,本方案提供了一種建立上述映射關系方法,提供了一種建立堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系的方法。本方法是利用現(xiàn)有的基數(shù)樹(Radix Tree)機制,建立一套任意地址與內(nèi)存域管理結(jié)構(gòu)映射關系的數(shù)據(jù)結(jié)構(gòu)。即將任一內(nèi)存地址與(&)域頁的結(jié)果作為基數(shù)樹索引,并在索引對應的元素位置保存對應的內(nèi)存域 管理結(jié)構(gòu)的指針;如果該內(nèi)存地址不是堆內(nèi)存則索引對應的元素保存0值。建立的步驟如下:初始化基數(shù)樹,將所有元素保存內(nèi)容置為0;在內(nèi)存分配器新建立內(nèi)存域時,向基數(shù)樹注冊新建內(nèi)存域所有域頁對應的內(nèi)存域管理結(jié)構(gòu)。即將所有域頁作為索引找到的元素的保存內(nèi)容修改為新建內(nèi)存域管理結(jié)構(gòu)指針;在內(nèi)存分配器銷毀內(nèi)存域時,向基數(shù)樹注銷新建內(nèi)存域所有域頁對應的內(nèi)存域管理結(jié)構(gòu)。即將所有域頁作為索引找到的元素的保存內(nèi)容修改為0。
可選地,步驟S1063,依據(jù)操作類型,以及確定的內(nèi)存塊的狀態(tài),判定操作的合法性的步驟可以分為如下至少一個方案:
方案一:
在操作類型為對內(nèi)存塊進行訪問,且內(nèi)存塊的狀態(tài)為已釋放的情況下,判定操作為訪問已釋放內(nèi)存塊的非法操作。
具體的,在上述內(nèi)存塊的尾部可以保存有內(nèi)存塊的當前狀態(tài)信息,在內(nèi)存的當前狀態(tài)為FREED(空閑狀態(tài))的時候,如果此時對上述內(nèi)存塊進行訪問,則判定本次操作為訪問已釋放內(nèi)存塊的非法訪問。
方案二:
在操作類型為對內(nèi)存塊進行讀操作,且內(nèi)存塊的初始化狀態(tài)為未初始化的情況下,判定操作為讀未初始化內(nèi)存塊的非法操作。
具體的,在上述內(nèi)存塊的尾部可以保存有內(nèi)存塊的當前狀態(tài)信息,該當前狀態(tài)信息可以為內(nèi)存塊的當前初始化狀態(tài),在內(nèi)存塊當前的初始化狀態(tài)為未初始化(此時內(nèi)存塊的初始化標志為1)的情況下,則判定本次讀操作為讀未初始化內(nèi)存塊的非法操作。
方案三:
在操作類型為對內(nèi)存塊進行釋放,且內(nèi)存塊的狀態(tài)為釋放狀態(tài)的情況下,判定操作為重復釋放內(nèi)存塊的非法操作。
具體的,可以根據(jù)釋放地址Pf通過上述預先定義好的映射關系去獲取該釋放地址對應內(nèi)存塊的狀態(tài),在內(nèi)存塊的當前狀態(tài)為FREED(空閑狀態(tài))的時候,則說明內(nèi)存塊以被釋放過,如果此時對上述內(nèi)存塊進行釋放,則判定本次操作為釋放已經(jīng)釋放的內(nèi)存塊的非法操作。
可選地,在上述內(nèi)存結(jié)構(gòu)信息中也可以包括堆內(nèi)存所包括的內(nèi)存塊的屬性信息,其中,上述步驟S106,依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測的步驟可以包括:
步驟S1064,確定操作在堆內(nèi)存塊中的操作范圍。
步驟S1066,依據(jù)操作范圍,以及內(nèi)存塊的屬性信息判定操作的合法性,其中,內(nèi)存塊的屬性信息包括:操作在堆內(nèi)存中對應的內(nèi)存塊的起始地址以及內(nèi)存塊的使用長度。
具體的,可以通過堆內(nèi)存的地址來獲取內(nèi)存塊的屬性信息,再通過操作范圍、內(nèi)存塊的屬性信息來對操作的合法性進行檢測。
仍舊以上述堆內(nèi)存可以由包含多個內(nèi)存塊的內(nèi)存域組成為例,提供一種依據(jù)操作范圍,以及內(nèi)存塊的起始地址和內(nèi)存塊的使用長度,判定操作的合法性的可選方案:
首先獲取編譯插樁機制提供的操作的訪問范圍以及本次內(nèi)存訪問的起始地址Ptr,利用上述獲取內(nèi)存塊的關鍵信息的方案獲取到Ptr對應的內(nèi)存塊起始地址Pb和內(nèi)存塊關鍵信息,在上述內(nèi)存塊關鍵信息中還可以記錄著內(nèi)存塊的使用長度USER_SIZE,則可以根據(jù)內(nèi)存塊起始地址Pb、內(nèi)存塊的使用長度USER_SIZE、本次訪問的訪問范圍來判定本次操作的合法性。
可選地,步驟S1066,依據(jù)操作范圍,以及內(nèi)存塊的起始地址和內(nèi)存塊的使用長度,判定操作的合法性的步驟可以包括:
步驟S10661,判斷操作范圍是否在內(nèi)存塊的起始地址和內(nèi)存塊的使用長度確定的范圍內(nèi)。
步驟S10662,在判斷結(jié)果為否的情況下,確定操作為越界非法操作。
具體的,可以讀出內(nèi)存塊的使用長度USER_SIZE,如果本次內(nèi)存訪問范圍不完全在Pb到Pb+USER_SIZE-1以內(nèi)則判定本次內(nèi)存操作是越界類型的非法訪問。
可選地,步驟S106,依據(jù)操作類型,以及內(nèi)存結(jié)構(gòu)信息對操作進行檢測的步驟還可以包括:
步驟S1067,在操作為釋放操作的情況下,確定操作的釋放地址。
步驟S1068,在內(nèi)存結(jié)構(gòu)信息中獲取不到釋放地址對應的屬性信息的情況下,判定操作為釋放非堆內(nèi)存地址的非法操作。
具體的,如果根據(jù)釋放地址Pf根據(jù)上述映射關系獲取不到該釋放地址對應的屬性信息的情況下,則說明該釋放地址Pf為不是堆內(nèi)存的地址,本次操作具體為釋放非堆內(nèi)存的非法操作。
可選地,如果根據(jù)上述釋放地址Pf獲取到了屬性信息,但是該內(nèi)存結(jié)構(gòu)信息中的內(nèi)存塊的屬性信息中的內(nèi)存塊的起始地址Pb不等于Pf的情況下,說明該釋放地址為一個錯誤地址,本次操作為釋放錯誤堆內(nèi)存地址的非法釋放操作。
可選地,堆內(nèi)存操作的檢測方法可以分為堆內(nèi)存的非法訪問檢測和非法釋放檢測,下面結(jié)合圖3和圖4對上述兩種檢測方法進行描述:
非法訪問檢測:
步驟S21:被檢測程序運行。
步驟S22:被檢測程序訪問內(nèi)存,觸發(fā)堆內(nèi)存非法訪問檢查。
步驟S23:利用堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系,判斷本次訪問內(nèi)存是否是堆內(nèi)存。如果不是則跳轉(zhuǎn)到步驟S31,如果是則執(zhí)行步驟S24。
步驟S24:檢查是否訪問未分配的內(nèi)存區(qū)域,即利用訪問未分配的內(nèi)存區(qū)域的檢測方法進行檢查,讀出內(nèi)存域狀態(tài),如果為未初始化狀態(tài)則判定本次內(nèi)存操作是訪問未分配的內(nèi)存區(qū)域的非法訪問,跳轉(zhuǎn)到步驟S30。如果為已初始化狀態(tài)則繼續(xù)下一步。
步驟S25:利用根據(jù)任一堆內(nèi)存地址找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法,獲取內(nèi)存塊起始地址Pb和記錄在內(nèi)存塊尾部的關鍵信息。
步驟S26:檢查是否是訪問已釋放的內(nèi)存塊,利用訪問已釋放內(nèi)存塊的檢測方法檢查。即從內(nèi)存塊關鍵信息讀出內(nèi)存塊狀態(tài),如果狀態(tài)為FREED則判定本次訪問是訪問已釋放內(nèi)存塊,跳轉(zhuǎn)到步驟S30。否則繼續(xù)下一步。
步驟S27:檢查是否為越界訪問,利用越界訪問的檢測方法檢查。即讀出內(nèi)存塊關鍵信息中的USER_SIZE,如果本次內(nèi)存訪問范圍不完全在Pb到Pb+USER_SIZE-1以內(nèi)則判定本次訪問是越界訪問,跳轉(zhuǎn)到步驟S30。否則繼續(xù)下一步。
步驟S28:檢查是否是讀未初始化內(nèi)存塊操作,利用讀未初始化內(nèi)存塊的檢測方法檢查。即從內(nèi)存塊關鍵信息中讀出內(nèi)存塊未初始化標志,如果標志為1且本次為讀訪問則判定本次訪問是讀未初始化內(nèi)存塊,跳轉(zhuǎn)到步驟S30。否則如果本次是寫訪問則將內(nèi)存塊未初始化標志置為0,并繼續(xù)下一步。
步驟S29:判定本次訪問合法,跳轉(zhuǎn)到步驟S31。
步驟S30:輸出檢測信息。
步驟S31:堆內(nèi)存非法訪問檢測結(jié)束,被檢測程序繼續(xù)運行。
非法釋放檢測:
步驟S10,被檢測程序運行。
步驟S20,被檢測程序釋放內(nèi)存,觸發(fā)堆內(nèi)存非法釋放檢測。
步驟S301,檢查是否為釋放非內(nèi)存。即根據(jù)釋放時傳入的地址Pf,利用堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系,查找Pf對應的內(nèi)存域。如果找不到對應的內(nèi)存域則判定為釋放非堆內(nèi)存,跳轉(zhuǎn)到步驟S80;否則執(zhí)行步驟S40。
步驟S40,利用根據(jù)任一堆內(nèi)存地址找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信 息的方法,獲取內(nèi)存塊起始地址Pb和記錄在內(nèi)存塊尾部的關鍵信息;
步驟S50,檢查是否是釋放已釋放的內(nèi)存塊。即從內(nèi)存塊關鍵信息讀出內(nèi)存塊狀態(tài),如果狀態(tài)為FREED則判定為重復釋放內(nèi)存,跳轉(zhuǎn)到步驟S80。否則執(zhí)行步驟S60。
步驟S60,檢查是否是釋放錯誤堆內(nèi)存地址,即如果Pf不等于Pb則判定為釋放錯誤堆內(nèi)存地址,跳轉(zhuǎn)到步驟S80;否則繼續(xù)下一步。
步驟S70,判定本次釋放合法,釋放內(nèi)存,跳轉(zhuǎn)到步驟S90。
步驟S80,輸出檢測信息。
步驟S90,堆內(nèi)存非法釋放檢測結(jié)束,被檢測程序繼續(xù)運行。
下面結(jié)合具體的實施例對堆內(nèi)存操作的檢測方法進行進一步的說明:
首先,本發(fā)明方法可以基于特定算法的堆內(nèi)存分配器來實現(xiàn)。這種特定算法的堆內(nèi)存分配器具有如下特性:特性一,堆內(nèi)存分配器基于一塊虛擬地址連續(xù)的大內(nèi)存區(qū)域(簡稱內(nèi)存域)來管理內(nèi)存,即以內(nèi)存域為單位向系統(tǒng)申請和釋放內(nèi)存;特性二,所有的內(nèi)存域始終按照特定的長度對齊(特定的長度本文稱之為域頁);特性三,提供用戶使用的內(nèi)存塊從內(nèi)存域中切割,一個內(nèi)存域可以切割若干內(nèi)存塊但一個內(nèi)存域切割的所有內(nèi)存塊長度相同;特性四,內(nèi)存域所有內(nèi)存完全、完整切分為內(nèi)存塊,沒有剩余內(nèi)存作它用;特性五,每一個內(nèi)存域存在一個對應的內(nèi)存域管理結(jié)構(gòu)記錄該內(nèi)存域起始地址、切割的內(nèi)存塊長度和初始化狀態(tài)(未初始化表示不可提供給用戶使用)等信息。內(nèi)存區(qū)域的結(jié)構(gòu)如圖2所示。
然后,本實施例可以提供一種記錄內(nèi)存塊關鍵信息的方法:可以利用現(xiàn)有的堆內(nèi)存分配接口接管方法,接管C庫提供的堆內(nèi)存分配/釋放接口,并在分配的內(nèi)存塊尾部插入內(nèi)存塊關鍵信息。其中,該內(nèi)存塊關鍵信息可以包括:內(nèi)存塊狀態(tài),即FREED和USED。FREED表示本內(nèi)存塊處于空閑狀態(tài);USED表示本內(nèi)存塊已分配給用戶使用。內(nèi)存塊關鍵信息還額可以包括:用戶希望申請的內(nèi)存塊大小(USER_SIZE),可選地,內(nèi)存塊關鍵信息還可以包括:未初始化標志,即本內(nèi)存塊未初始化則標志為1,初始化后標志置為0。
接著,本實施例還可以提供一種建立堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系的方法。該方法是利用現(xiàn)有的基數(shù)樹(Radix Tree)機制,建立一套任意地址與內(nèi)存域管理結(jié)構(gòu)映射關系的數(shù)據(jù)結(jié)構(gòu)。即將任一內(nèi)存地址與(&)域頁的結(jié)果作為基數(shù)樹索引,并在索引對應的元素位置保存對應的內(nèi)存域管理結(jié)構(gòu)的指針;如果該內(nèi)存地址不是堆內(nèi)存則索引對應的元素保存0值。本方法具體步驟如下:初始化基數(shù)樹,將所有元素保存內(nèi)容置為0;在內(nèi)存分配器新建立內(nèi)存域時,向基數(shù)樹注冊新建內(nèi)存域所有域頁對應的內(nèi)存域管理結(jié)構(gòu)。即將所有域頁作為索引找到的元素的保存內(nèi)容修改為新建內(nèi)存域管理結(jié)構(gòu)指針;在內(nèi)存分配器銷毀內(nèi)存域時,向基數(shù)樹注銷新建內(nèi)存域所有域頁對應的內(nèi)存域 管理結(jié)構(gòu)。即將所有域頁作為索引找到的元素的保存內(nèi)容修改為0。
接著,本實施例還可以提供一種根據(jù)堆內(nèi)存地址Ptr找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法。本方法具體步驟如下:根據(jù)堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系,找出堆內(nèi)存地址對應的內(nèi)存域管理結(jié)構(gòu),讀出內(nèi)存域的起始地址P0和內(nèi)存塊長度Sb;根據(jù)公式計算出Ptr對應的內(nèi)存塊的起始地址Pb;Pb加上Sb再減去內(nèi)存塊關鍵信息的大小Si,即可獲得該內(nèi)存塊關鍵信息的起始地址。
基于上述記錄內(nèi)存塊關鍵信息的方法、建立堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系的方法、根據(jù)堆內(nèi)存地址Ptr找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法,本實施例可以提供堆內(nèi)存非法訪問的檢測方法。需要說明的是,堆內(nèi)存非法訪問的檢測點是利用編譯器編譯插樁機制實現(xiàn)的,即在被檢測軟件進行內(nèi)存訪問時進行。編譯插樁機制提供本次內(nèi)存訪問的起始地址和訪問范圍。上述堆內(nèi)存非法訪問的檢測方法包括:訪問未分配的內(nèi)存區(qū)域的檢測方法。根據(jù)編譯插樁機制提供本次內(nèi)存訪問的起始地址Ptr,利用堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系,找出Ptr對應的內(nèi)存域,如果內(nèi)存域的狀態(tài)為未初始化,則判定本次內(nèi)存操作是訪問未分配的內(nèi)存區(qū)域的非法訪問。
可選地,堆內(nèi)存非法訪問的檢測方法還可以包括:訪問已釋放內(nèi)存塊的檢測方法。根據(jù)編譯插樁機制提供本次內(nèi)存訪問的起始地址Ptr,利用任一堆內(nèi)存地址找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法,獲取內(nèi)存塊關鍵信息。讀出內(nèi)存塊關鍵信息中的內(nèi)存塊狀態(tài),如果內(nèi)存塊狀態(tài)為FREED則判定本次內(nèi)存操作是訪問已釋放內(nèi)存塊的非法訪問。
可選地,堆內(nèi)存非法訪問的檢測方法還包括:越界訪問的檢測方法。根據(jù)編譯插樁機制提供本次內(nèi)存訪問的起始地址Ptr,利用任一堆內(nèi)存地址找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法,獲取Ptr對應的內(nèi)存塊起始地址Pb和內(nèi)存塊關鍵信息。讀出內(nèi)存塊關鍵信息中的USER_SIZE,如果本次內(nèi)存訪問范圍不完全在Pb到Pb+USER_SIZE-1以內(nèi)則判定本次內(nèi)存操作是越界類型的非法訪問。
可選地,堆內(nèi)存非法訪問的檢測方法還包括:讀未初始化內(nèi)存塊的檢測方法。該方法具體步驟如下:內(nèi)存塊分配時利用記錄內(nèi)存塊關鍵信息的方法將關鍵信息中的未初始化標志置為1;內(nèi)存訪問時,根據(jù)編譯插樁機制提供本次內(nèi)存訪問的起始地址Ptr,利用任一堆內(nèi)存地址找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法,獲取內(nèi)存塊關鍵信息,讀出內(nèi)存塊未初始化標志。如果本次訪問是寫訪問則將未初始化標志置為0;如果本次是讀訪問,則判斷內(nèi)存塊未初始化標志是否為1,如果為1則判定本次操作是讀未初始化內(nèi)存塊的非法操作。
可選地,本實施例還可以提供內(nèi)存非法釋放的檢測方法。
內(nèi)存非法釋放的檢測方法包括:釋放非堆內(nèi)存的檢測方法。根據(jù)釋放時傳入的地址 Pf,利用堆內(nèi)存地址和內(nèi)存域管理結(jié)構(gòu)的映射關系,查找Pf對應的內(nèi)存域。如果找不到對應的內(nèi)存域則表明Pf并不是堆內(nèi)存地址,即可判定本次內(nèi)存操作是釋放非堆內(nèi)存的非法釋放。
可選地,內(nèi)存非法釋放的檢測方法還包括:重復釋放內(nèi)存塊的檢測方法。根據(jù)釋放時傳入的地址Pf,利用任一堆內(nèi)存地址找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法,獲取內(nèi)存塊關鍵信息。讀出內(nèi)存塊關鍵信息中的內(nèi)存塊狀態(tài),如果內(nèi)存塊狀態(tài)為FREED則判定本次內(nèi)存操作是重復釋放內(nèi)存塊的非法釋放。
可選地,內(nèi)存非法釋放的檢測方法還包括:釋放錯誤堆內(nèi)存地址的檢測方法。根據(jù)釋放時傳入的地址Pf,利用任一堆內(nèi)存地址找到其所屬的內(nèi)存塊起始地址和內(nèi)存塊關鍵信息的方法,獲取內(nèi)存塊起始地址Pb。如果Pf不等于Pb則判定本次內(nèi)存操作是釋放錯誤堆內(nèi)存地址的非法釋放。
綜上,針對現(xiàn)有檢測工具檢測類型較少、內(nèi)存消耗大、檢測效率低下的缺陷,本申請的方案可以實現(xiàn)效果如下:能實現(xiàn)檢查各種堆內(nèi)存違法的、內(nèi)存消耗更低和更加快速的堆內(nèi)存非法操作檢測方法。
通過以上的實施方式的描述,本領域的技術人員可以清楚地了解到根據(jù)上述實施例的方法可借助軟件加必需的通用硬件平臺的方式來實現(xiàn),當然也可以通過硬件,但很多情況下前者是更佳的實施方式?;谶@樣的理解,本發(fā)明的技術方案本質(zhì)上或者說對現(xiàn)有技術做出貢獻的部分可以以軟件產(chǎn)品的形式體現(xiàn)出來,該計算機軟件產(chǎn)品存儲在一個存儲介質(zhì)(如ROM/RAM、磁碟、光盤)中,包括若干指令用以使得一臺終端設備(可以是手機,計算機,服務器,或者網(wǎng)絡設備等)執(zhí)行本發(fā)明各個實施例的方法。
在本實施例中還提供了一種堆內(nèi)存操作的檢測裝置,該裝置用于實現(xiàn)上述實施例及優(yōu)選實施方式,已經(jīng)進行過說明的不再贅述。如以下所使用的,術語“模塊”可以實現(xiàn)預定功能的軟件和/或硬件的組合。盡管以下實施例所描述的裝置較佳地以軟件來實現(xiàn),但是硬件,或者軟件和硬件的組合的實現(xiàn)也是可能并被構(gòu)想的。
圖5是根據(jù)本發(fā)明實施例的堆內(nèi)存操作的檢測裝置的結(jié)構(gòu)框圖,如圖5所示,該裝置包括:確定模塊50,用于確定對堆內(nèi)存進行操作的操作類型;獲取模塊52,用于獲取用于表述所述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息;檢測模塊54,用于依據(jù)所述操作類型,以及所述內(nèi)存結(jié)構(gòu)信息對所述操作進行檢測。
可選地,檢測模塊54可以包括:第一確定單元,用于確定所述操作在所述堆內(nèi)存所對應的內(nèi)存塊;第二確定單元,用于依據(jù)所述內(nèi)存塊的狀態(tài)信息確定所述內(nèi)存塊的狀態(tài);第一判斷單元,用于依據(jù)所述操作類型,以及確定的所述內(nèi)存塊的狀態(tài),判定所述操作的合法性。
可選地,上述第一判斷單元可以包括至少如下子單元之一:第一判斷子單元,用于 在所述操作類型為對所述內(nèi)存塊進行訪問,且所述內(nèi)存塊的狀態(tài)為已釋放的情況下,判定所述操作為訪問已釋放內(nèi)存塊的非法操作;第二判斷子單元,用于在所述操作類型為對所述內(nèi)存塊進行讀操作,且所述內(nèi)存塊的初始化狀態(tài)為未初始化的情況下,判定所述操作為讀未初始化內(nèi)存塊的非法操作;第三判斷子單元,用于在所述操作類型為對所述內(nèi)存塊進行釋放,且所述內(nèi)存塊的狀態(tài)為釋放狀態(tài)的情況下,判定所述操作為重復釋放內(nèi)存塊的非法操作。
可選地,上述檢測模塊54還可以包括:第三確定單元,用于確定操作在堆內(nèi)存塊中的操作范圍;第二判斷單元,用于依據(jù)操作范圍,以及內(nèi)存塊的屬性信息判定操作的合法性,其中,內(nèi)存塊的屬性信息包括:操作在堆內(nèi)存中對應的內(nèi)存塊的起始地址以及內(nèi)存塊的使用長度。
可選地,上述第二判斷單元可以包括:第四判斷子單元,用于判斷所述操作范圍是否在所述內(nèi)存塊的起始地址和所述內(nèi)存塊的使用長度確定的范圍內(nèi);第一確定子單元,用于在判斷結(jié)果為否的情況下,確定所述操作為越界非法操作。
可選地,檢測模塊54還可以包括:第二確定子單元,用于在所述操作為釋放操作的情況下,確定所述操作的釋放地址,第五判斷子單元,用于在所述內(nèi)存結(jié)構(gòu)信息中獲取不到所述釋放地址對應的信息的情況下,判定所述操作為釋放錯誤釋堆非內(nèi)存地址的非法操作。
本發(fā)明的實施例還提供了一種存儲介質(zhì)??蛇x地,在本實施例中,上述存儲介質(zhì)可以被設置為存儲用于執(zhí)行以下步驟的程序代碼:
S1,確定對堆內(nèi)存進行操作的操作類型。
S2,獲取用于表述所述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息。
S3,依據(jù)所述操作類型,以及所述內(nèi)存結(jié)構(gòu)信息對所述操作進行檢測。
可選地,存儲介質(zhì)還被設置為存儲用于執(zhí)行以下步驟的程序代碼:
S1,確定所述操作在所述堆內(nèi)存所對應的內(nèi)存塊;
S2,依據(jù)所述內(nèi)存塊的狀態(tài)信息確定所述內(nèi)存塊的狀態(tài);
S3,依據(jù)所述操作類型,以及確定的所述內(nèi)存塊的狀態(tài),判定所述操作的合法性。
可選地,存儲介質(zhì)還被設置為存儲用于執(zhí)行以下步驟的程序代碼:
S1,在所述操作類型為對所述內(nèi)存塊進行訪問,且所述內(nèi)存塊的狀態(tài)為已釋放的情況下,判定所述操作為訪問已釋放內(nèi)存塊的非法操作;
S2,在所述操作類型為對所述內(nèi)存塊進行讀操作,且所述內(nèi)存塊的初始化狀態(tài)為未初始化的情況下,判定所述操作為讀未初始化內(nèi)存塊的非法操作;
S3,在所述操作類型為對所述內(nèi)存塊進行釋放,且所述內(nèi)存塊的狀態(tài)為已釋放的情況下,判定所述操作為重復釋放內(nèi)存塊的非法操作。
可選地,存儲介質(zhì)還被設置為存儲用于執(zhí)行以下步驟的程序代碼:
S1,確定所述操作在所述堆內(nèi)存塊中的操作范圍;
S2,依據(jù)所述操作范圍,以及所述內(nèi)存塊的屬性信息判定所述操作的合法性,其中,所述內(nèi)存塊的屬性信息包括:所述操作在所述堆內(nèi)存中對應的內(nèi)存塊的起始地址以及所述內(nèi)存塊的使用長度。
可選地,存儲介質(zhì)還被設置為存儲用于執(zhí)行以下步驟的程序代碼:
S1,判斷所述操作范圍是否在所述內(nèi)存塊的起始地址和所述內(nèi)存塊的使用長度確定的范圍內(nèi);
S2,在判斷結(jié)果為否的情況下,確定所述操作為越界非法操作。
可選地,存儲介質(zhì)還被設置為存儲用于執(zhí)行以下步驟的程序代碼:
S1,在所述操作為釋放操作的情況下,確定所述操作的釋放地址;
S2,在所述內(nèi)存結(jié)構(gòu)信息中獲取不到所述釋放地址對應的所述屬性信息的情況下,判定所述操作為釋放非內(nèi)存地址的非法操作。
可選地,在本實施例中,上述存儲介質(zhì)可以包括但不限于:U盤、只讀存儲器(ROM,Read-Only Memory)、隨機存取存儲器(RAM,Random Access Memory)、移動硬盤、磁碟或者光盤等各種可以存儲程序代碼的介質(zhì)。
可選地,在本實施例中,處理器根據(jù)存儲介質(zhì)中已存儲的程序代碼執(zhí)行:
S1,確定對堆內(nèi)存進行操作的操作類型。
S2,獲取用于表述所述堆內(nèi)存的內(nèi)存結(jié)構(gòu)信息。
S3,依據(jù)所述操作類型,以及所述內(nèi)存結(jié)構(gòu)信息對所述操作進行檢測。
可選地,在本實施例中,處理器根據(jù)存儲介質(zhì)中已存儲的程序代碼執(zhí)行:
S1,確定所述操作在所述堆內(nèi)存所對應的內(nèi)存塊;
S2,依據(jù)所述內(nèi)存塊的狀態(tài)信息確定所述內(nèi)存塊的狀態(tài);
S3,依據(jù)所述操作類型,以及確定的所述內(nèi)存塊的狀態(tài),判定所述操作的合法性。
可選地,在本實施例中,處理器根據(jù)存儲介質(zhì)中已存儲的程序代碼執(zhí)行:
S1,在所述操作類型為對所述內(nèi)存塊進行訪問,且所述內(nèi)存塊的狀態(tài)為已釋放的情 況下,判定所述操作為訪問已釋放內(nèi)存塊的非法操作;
S2,在所述操作類型為對所述內(nèi)存塊進行讀操作,且所述內(nèi)存塊的初始化狀態(tài)為未初始化的情況下,判定所述操作為讀未初始化內(nèi)存塊的非法操作;
S3,在所述操作類型為對所述內(nèi)存塊進行釋放,且所述內(nèi)存塊的狀態(tài)為已釋放的情況下,判定所述操作為重復釋放內(nèi)存塊的非法操作。
可選地,在本實施例中,處理器根據(jù)存儲介質(zhì)中已存儲的程序代碼執(zhí)行:
S1,確定所述操作在所述堆內(nèi)存塊中的操作范圍;
S2,依據(jù)所述操作范圍,以及所述內(nèi)存塊的屬性信息判定所述操作的合法性,其中,所述內(nèi)存塊的屬性信息包括:所述操作在所述堆內(nèi)存中對應的內(nèi)存塊的起始地址以及所述內(nèi)存塊的使用長度。
可選地,在本實施例中,處理器根據(jù)存儲介質(zhì)中已存儲的程序代碼執(zhí)行:
S1,判斷所述操作范圍是否在所述內(nèi)存塊的起始地址和所述內(nèi)存塊的使用長度確定的范圍內(nèi);
S2,在判斷結(jié)果為否的情況下,確定所述操作為越界非法操作。
可選地,在本實施例中,處理器根據(jù)存儲介質(zhì)中已存儲的程序代碼執(zhí)行:
S1,在所述操作為釋放操作的情況下,確定所述操作的釋放地址;
S2,在所述內(nèi)存結(jié)構(gòu)信息中獲取不到所述釋放地址對應的所述屬性信息的情況下,判定所述操作為釋放非內(nèi)存地址的非法操作。
可選地,本實施例中的具體示例可以參考上述實施例及可選實施方式中所描述的示例,本實施例在此不再贅述。
顯然,本領域的技術人員應該明白,上述的本發(fā)明的各模塊或各步驟可以用通用的計算裝置來實現(xiàn),它們可以集中在單個的計算裝置上,或者分布在多個計算裝置所組成的網(wǎng)絡上,可選地,它們可以用計算裝置可執(zhí)行的程序代碼來實現(xiàn),從而,可以將它們存儲在存儲裝置中由計算裝置來執(zhí)行,并且在某些情況下,可以以不同于此處的順序執(zhí)行所示出或描述的步驟,或者將它們分別制作成各個集成電路模塊,或者將它們中的多個模塊或步驟制作成單個集成電路模塊來實現(xiàn)。這樣,本發(fā)明不限制于任何特定的硬件和軟件結(jié)合。
以上所述僅為本發(fā)明的優(yōu)選實施例而已,并不用于限制本發(fā)明,對于本領域的技術人員來說,本發(fā)明可以有各種更改和變化。凡在本發(fā)明的精神和原則之內(nèi),所作的任何修改、等同替換、改進等,均應包含在本發(fā)明的保護范圍之內(nèi)。