本發(fā)明涉及內(nèi)存管理技術(shù)領(lǐng)域,尤其涉及一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位方法及其系統(tǒng)。
背景技術(shù):
在c語(yǔ)言環(huán)境下,內(nèi)存的分配和釋放,可以直接使用系統(tǒng)申請(qǐng)/釋放函數(shù)接口。但是有以下弊端:
1、調(diào)用系統(tǒng)函數(shù),相對(duì)比較耗時(shí);
2、頻繁使用會(huì)產(chǎn)生大量的內(nèi)存碎片,從而降低程序運(yùn)行效率。
為了避免以上問(wèn)題,在項(xiàng)目中一般使用內(nèi)存池來(lái)代替系統(tǒng)函數(shù)進(jìn)行內(nèi)存管理。內(nèi)存池的初始結(jié)構(gòu)如圖1所示,在真正使用內(nèi)存之前,預(yù)先分配一定數(shù)量的內(nèi)存塊,當(dāng)需要申請(qǐng)內(nèi)存時(shí),就從這些預(yù)先分配的內(nèi)存塊中選擇,而不是直接使用系統(tǒng)函數(shù)進(jìn)行分配。內(nèi)存塊被分配后,如圖2所示。
內(nèi)存池算法一般關(guān)注于管理內(nèi)存(分配算法、釋放算法、不定長(zhǎng)內(nèi)存塊算法等),而沒(méi)有關(guān)注于內(nèi)存池的穩(wěn)定,即快速定位內(nèi)存池泄露、內(nèi)存塊使用時(shí)越界問(wèn)題。
內(nèi)存池泄露是指在從內(nèi)存池分配一個(gè)內(nèi)存塊后,應(yīng)該被釋放而沒(méi)有被釋放的情況;內(nèi)存塊使用時(shí)越界與數(shù)組越界類似,比如向10字節(jié)大小的內(nèi)存塊寫入20字節(jié)的數(shù)據(jù)。內(nèi)存池泄露會(huì)導(dǎo)致內(nèi)存最后耗盡,而越界則會(huì)導(dǎo)致程序運(yùn)行不穩(wěn)定。良好的編程習(xí)慣可以預(yù)防一部分的內(nèi)存池泄露、越界等問(wèn)題,但是,隨著項(xiàng)目代碼量的增加以及多人協(xié)作,完全避免幾乎是不可能做到的。內(nèi)存泄露和數(shù)組越界很容易引入,而難以定位,尤其是代碼量龐大、多線程的環(huán)境中更難以定位。
一般,使用mtrace、valgrind定位內(nèi)存泄露。而對(duì)于越界,則更難以處理,例如下述的代碼:
程序編譯時(shí)并不能發(fā)現(xiàn),且在程序運(yùn)行時(shí)并不一定會(huì)發(fā)生,只有在外部輸入超過(guò)10個(gè)字符的時(shí)候才會(huì)發(fā)生越界。
對(duì)于lte協(xié)議棧,由于接入層的時(shí)序要求,它的調(diào)度周期是1毫秒,即在每1個(gè)毫秒內(nèi),必須完成接入設(shè)備的調(diào)度、資源的分配、編碼等等,所以,lte協(xié)議棧的時(shí)序要求十分嚴(yán)格,即使在嵌入式環(huán)境下mtrace、valgrind可以移植使用,在跑lte協(xié)議棧時(shí)使用不了,它會(huì)嚴(yán)重影響協(xié)議棧的運(yùn)行性能,導(dǎo)致不能正常工作。
在公開(kāi)號(hào)為cn105988921a的中國(guó)專利公開(kāi)文件中,提出了一種內(nèi)存越界的檢測(cè)方法及裝置,其方法包括:獲取分配給待檢測(cè)程序的內(nèi)存塊的起始地址和內(nèi)存管理頭信息,內(nèi)存管理頭信息包括:內(nèi)存塊的容量以及釋放標(biāo)記;檢測(cè)釋放標(biāo)記,若釋放標(biāo)記指示內(nèi)存塊已被釋放,則判斷待檢測(cè)程序發(fā)生內(nèi)存越界;若釋放標(biāo)記指示內(nèi)存塊未被釋放,則獲取待檢測(cè)程序的第一偏向地址,第一偏向地址為距起始地址最遠(yuǎn)的偏向地址;根據(jù)內(nèi)存塊的容量和起始地址,檢測(cè)第一偏向地址是否落在內(nèi)存塊的內(nèi)存范圍內(nèi);若第一偏向地址未落在內(nèi)存塊的內(nèi)存范圍內(nèi),則判斷待檢測(cè)程序發(fā)生內(nèi)存越界。但該方案的越界定位準(zhǔn)確率不高,例如,物理上連續(xù)的內(nèi)存塊1-4,假設(shè)在內(nèi)存塊1越界并修改內(nèi)存塊2-4的內(nèi)容,該方案找出的可能是內(nèi)存塊4的越界。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明所要解決的技術(shù)問(wèn)題是:提出一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位方法及其系統(tǒng),可快速定位出內(nèi)存泄露位置和內(nèi)存越界位置。
為了解決上述技術(shù)問(wèn)題,本發(fā)明采用的技術(shù)方案為:一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位方法,包括:
在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、分配標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值;
若一內(nèi)存塊被分配,則將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)已分配的第一字符,將所述一內(nèi)存塊的字符串指針設(shè)置為申請(qǐng)所述一內(nèi)存塊的函數(shù)名,將所述一內(nèi)存塊的位置變量設(shè)置為申請(qǐng)所述一內(nèi)存塊的代碼所處的行數(shù);
當(dāng)所述一內(nèi)存塊被釋放后,將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)未分配的第二字符;
當(dāng)所述一內(nèi)存塊重新放入內(nèi)存池時(shí),分別檢測(cè)所述一內(nèi)存塊的第一標(biāo)記和第二標(biāo)記是否與預(yù)設(shè)的參數(shù)值一致;
若所述一內(nèi)存塊的第一標(biāo)記與其預(yù)設(shè)的參數(shù)值一致且第二標(biāo)記與其預(yù)設(shè)的參數(shù)值不一致,則判定所述一內(nèi)存塊越界;
根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存越界的位置;
若內(nèi)存池的使用率超過(guò)預(yù)設(shè)的閾值,則獲取分配標(biāo)記為第二字符的內(nèi)存塊;
根據(jù)所獲取的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存泄露位置。
本發(fā)明還涉及一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位系統(tǒng),包括:
第一設(shè)置模塊,用于在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、分配標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值;
第二設(shè)置模塊,用于若一內(nèi)存塊被分配,則將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)已分配的第一字符,將所述一內(nèi)存塊的字符串指針設(shè)置為申請(qǐng)所述一內(nèi)存塊的函數(shù)名,將所述一內(nèi)存塊的位置變量設(shè)置為申請(qǐng)所述一內(nèi)存塊的代碼所處的行數(shù);
第三設(shè)置模塊,用于當(dāng)所述一內(nèi)存塊被釋放后,將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)未分配的第二字符;
檢測(cè)模塊,用于當(dāng)所述一內(nèi)存塊重新放入內(nèi)存池時(shí),分別檢測(cè)所述一內(nèi)存塊的第一標(biāo)記和第二標(biāo)記是否與預(yù)設(shè)的參數(shù)值一致;
判定模塊,用于若所述一內(nèi)存塊的第一標(biāo)記與其預(yù)設(shè)的參數(shù)值一致且第二標(biāo)記與其預(yù)設(shè)的參數(shù)值不一致,則判定所述一內(nèi)存塊越界;
第一定位模塊,用于根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存越界的位置;
獲取模塊,用于若內(nèi)存池的使用率超過(guò)預(yù)設(shè)的閾值,則獲取分配標(biāo)記為第二字符的內(nèi)存塊;
第二定位模塊,用于根據(jù)所獲取的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存泄露位置。
本發(fā)明的有益效果在于:通過(guò)在內(nèi)存塊中加入記錄該內(nèi)存中分配狀態(tài)的分配標(biāo)記,以及記錄申請(qǐng)?jiān)搩?nèi)存塊的函數(shù)名和函數(shù)位置的字符串指針和位置變量,即可在內(nèi)存泄露,即內(nèi)存池中超過(guò)預(yù)設(shè)個(gè)數(shù)的內(nèi)存塊都處于分配狀態(tài)時(shí),快速地定位出內(nèi)存泄露的位置;同時(shí),在內(nèi)存塊的頭尾分別加入第一標(biāo)記和第二標(biāo)記,可在內(nèi)存塊釋放時(shí),通過(guò)檢測(cè)第一標(biāo)記和第二標(biāo)記來(lái)判斷該內(nèi)存塊是否發(fā)生越界,定位到發(fā)生越界的內(nèi)存塊,再根據(jù)該內(nèi)存塊所記錄的函數(shù)名和函數(shù)位置,定位到內(nèi)存越界的具體位置;本發(fā)明可在滿足lte嚴(yán)格時(shí)序要求,不影響協(xié)議棧正常工作的情況下(每毫秒增加耗時(shí)1微妙以內(nèi),即影響在千分之1以內(nèi))解決內(nèi)存池的內(nèi)存泄露及內(nèi)存越界問(wèn)題。
附圖說(shuō)明
圖1為現(xiàn)有技術(shù)的內(nèi)存池結(jié)構(gòu)示意圖;
圖2為現(xiàn)有技術(shù)的內(nèi)存塊被分配后的示意圖;
圖3為本發(fā)明一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位方法流程圖;
圖4為本發(fā)明實(shí)施例一的內(nèi)存池泄露的定位方法流程圖;
圖5為本發(fā)明實(shí)施例一的步驟s106的方法流程圖;
圖6為本發(fā)明實(shí)施例一的內(nèi)存塊越界的定位方法流程圖;
圖7為本發(fā)明實(shí)施例一的步驟s206的方法流程圖;
圖8為本發(fā)明實(shí)施例一的內(nèi)存塊結(jié)構(gòu)示意圖;
圖9為本發(fā)明實(shí)施例二的方法流程圖;
圖10為本發(fā)明實(shí)施例二的內(nèi)存池結(jié)構(gòu)示意圖;
圖11為本發(fā)明實(shí)施例二的內(nèi)存塊分配示意圖;
圖12為本發(fā)明實(shí)施例二的內(nèi)存塊釋放示意圖;
圖13為本發(fā)明實(shí)施例三分配前后的內(nèi)存塊結(jié)構(gòu)示意圖;
圖14為本發(fā)明實(shí)施例三內(nèi)存池情況示意圖;
圖15為本發(fā)明實(shí)施例三內(nèi)存塊越界前后對(duì)比示意圖;
圖16為一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位系統(tǒng)的結(jié)構(gòu)示意圖;
圖17為本發(fā)明實(shí)施例四的系統(tǒng)結(jié)構(gòu)示意圖。
標(biāo)號(hào)說(shuō)明:
1、第一設(shè)置模塊;2、第二設(shè)置模塊;3、第三設(shè)置模塊;4、檢測(cè)模塊;
5、判定模塊;6、第一定位模塊;7、獲取模塊;8、第二定位模塊;9、定義模塊;10、放入模塊;11、連接模塊;12、申請(qǐng)模塊;13、分配模塊;
14、第一指向模塊;15、確定模塊;16、第二指向模塊;
61、第一獲取單元;62、第二獲取單元;63、第三獲取單元;64、第一定位單元;
81、第四獲取單元;82、第五獲取單元;83、第二定位單元。
具體實(shí)施方式
為詳細(xì)說(shuō)明本發(fā)明的技術(shù)內(nèi)容、所實(shí)現(xiàn)目的及效果,以下結(jié)合實(shí)施方式并配合附圖詳予說(shuō)明。
本發(fā)明最關(guān)鍵的構(gòu)思在于:在內(nèi)存塊的頭尾加入標(biāo)記以及記錄申請(qǐng)?jiān)搩?nèi)存塊的函數(shù)名和函數(shù)位置的字符串指針和位置變量。
請(qǐng)參閱圖3,一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位方法,包括:
在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、分配標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值;
若一內(nèi)存塊被分配,則將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)已分配的第一字符,將所述一內(nèi)存塊的字符串指針設(shè)置為申請(qǐng)所述一內(nèi)存塊的函數(shù)名,將所述一內(nèi)存塊的位置變量設(shè)置為申請(qǐng)所述一內(nèi)存塊的代碼所處的行數(shù);
當(dāng)所述一內(nèi)存塊被釋放后,將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)未分配的第二字符;
當(dāng)所述一內(nèi)存塊重新放入內(nèi)存池時(shí),分別檢測(cè)所述一內(nèi)存塊的第一標(biāo)記和第二標(biāo)記是否與預(yù)設(shè)的參數(shù)值一致;
若所述一內(nèi)存塊的第一標(biāo)記與其預(yù)設(shè)的參數(shù)值一致且第二標(biāo)記與其預(yù)設(shè)的參數(shù)值不一致,則判定所述一內(nèi)存塊越界;
根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存越界的位置;
若內(nèi)存池的使用率超過(guò)預(yù)設(shè)的閾值,則獲取分配標(biāo)記為第二字符的內(nèi)存塊;
根據(jù)所獲取的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存泄露位置。
從上述描述可知,本發(fā)明的有益效果在于:可在滿足lte嚴(yán)格時(shí)序要求,不影響協(xié)議棧正常工作的情況下,解決內(nèi)存池的內(nèi)存泄露及內(nèi)存越界問(wèn)題。
進(jìn)一步地,所述“根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存越界的位置”具體為:
根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),獲取申請(qǐng)所述一內(nèi)存塊的第一代碼位置;
根據(jù)gdb或backtrace函數(shù)獲取函數(shù)棧信息;
根據(jù)所述函數(shù)棧信息,獲取釋放所述一內(nèi)存塊的第二代碼位置;
根據(jù)所述第一代碼位置和第二代碼位置,定位內(nèi)存越界的位置。
由上述描述可知,通過(guò)獲取申請(qǐng)發(fā)生越界的內(nèi)存塊的位置以及釋放發(fā)生越界的內(nèi)存塊的位置,即定位出線索的頭尾,由此即可定位到發(fā)生越界的具體位置。
進(jìn)一步地,所述“根據(jù)所述獲取的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存泄露位置”具體為:
獲取分配標(biāo)記為第二字符的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù);
獲取所述函數(shù)名和行數(shù)中出現(xiàn)次數(shù)最多的函數(shù)名和行數(shù);
根據(jù)所獲取的函數(shù)名和行數(shù),定位內(nèi)存泄露位置。
由上述描述可知,通過(guò)記錄申請(qǐng)內(nèi)存塊的函數(shù)及函數(shù)代碼位置,在內(nèi)存池泄露發(fā)生時(shí),查看沒(méi)有釋放的內(nèi)存塊中,哪個(gè)函數(shù)出現(xiàn)的次數(shù)異常多,即可確認(rèn)該函數(shù)發(fā)生了內(nèi)存泄露。
進(jìn)一步地,所述“在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、分配標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值”之前,進(jìn)一步包括:
定義兩組以上不同大小的內(nèi)存塊,其中,同一組內(nèi)的各內(nèi)存塊的大小一致;
將同一組的內(nèi)存塊按照預(yù)設(shè)的順序放入同一內(nèi)存池,并將所述內(nèi)存池的鏈表頭指針指向最后放入的內(nèi)存塊,將所述內(nèi)存池的鏈表尾指針指向最先放入的內(nèi)存塊;
將各內(nèi)存池的鏈表頭指針和鏈表尾指針通過(guò)數(shù)組進(jìn)行連接;
申請(qǐng)內(nèi)存時(shí),選擇內(nèi)存塊大小與所申請(qǐng)的內(nèi)存大小最接近的內(nèi)存池;
內(nèi)存塊分配時(shí),將所述內(nèi)存池中的第一個(gè)內(nèi)存塊作為被分配的內(nèi)存塊從鏈表中刪除,將所述內(nèi)存池中的第二個(gè)內(nèi)存塊的next指針指向空,將鏈表尾指針指向所述第二個(gè)內(nèi)存塊;
將被分配的內(nèi)存塊的next指針指向鏈表頭;
內(nèi)存塊釋放時(shí),根據(jù)其所指向的鏈表頭,確定對(duì)應(yīng)的內(nèi)存池;
將被釋放的內(nèi)存塊的next指針指向?qū)?yīng)的內(nèi)存池中的最后一個(gè)內(nèi)存塊,并將所述內(nèi)存池的鏈表頭指針指向所述內(nèi)存塊。
由上述描述可知,對(duì)內(nèi)存池的操作,只有改變2-4個(gè)鏈表指針的操作,有效地提高了內(nèi)存池的處理效率。
請(qǐng)參照?qǐng)D16,本發(fā)明還提出了一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位系統(tǒng),包括:
第一設(shè)置模塊,用于在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、分配標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值;
第二設(shè)置模塊,用于若一內(nèi)存塊被分配,則將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)已分配的第一字符,將所述一內(nèi)存塊的字符串指針設(shè)置為申請(qǐng)所述一內(nèi)存塊的函數(shù)名,將所述一內(nèi)存塊的位置變量設(shè)置為申請(qǐng)所述一內(nèi)存塊的代碼所處的行數(shù);
第三設(shè)置模塊,用于當(dāng)所述一內(nèi)存塊被釋放后,將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)未分配的第二字符;
檢測(cè)模塊,用于當(dāng)所述一內(nèi)存塊重新放入內(nèi)存池時(shí),分別檢測(cè)所述一內(nèi)存塊的第一標(biāo)記和第二標(biāo)記是否與預(yù)設(shè)的參數(shù)值一致;
判定模塊,用于若所述一內(nèi)存塊的第一標(biāo)記與其預(yù)設(shè)的參數(shù)值一致且第二標(biāo)記與其預(yù)設(shè)的參數(shù)值不一致,則判定所述一內(nèi)存塊越界;
第一定位模塊,用于根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存越界的位置;
獲取模塊,用于若內(nèi)存池的使用率超過(guò)預(yù)設(shè)的閾值,則獲取分配標(biāo)記為第二字符的內(nèi)存塊;
第二定位模塊,用于根據(jù)所獲取的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存泄露位置。
進(jìn)一步地,所述第一定位模塊包括:
第一獲取單元,用于根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),獲取申請(qǐng)所述一內(nèi)存塊的第一代碼位置;
第二獲取單元,用于根據(jù)gdb或backtrace函數(shù)獲取函數(shù)棧信息;
第三獲取單元,用于根據(jù)所述函數(shù)棧信息,獲取釋放所述一內(nèi)存塊的第二代碼位置;
第一定位單元,用于根據(jù)所述第一代碼位置和第二代碼位置,定位內(nèi)存越界的位置。
進(jìn)一步地,所述第二定位模塊包括:
第四獲取單元,用于獲取分配標(biāo)記為第二字符的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù);
第五獲取單元,用于獲取所述函數(shù)名和行數(shù)中出現(xiàn)次數(shù)最多的函數(shù)名和行數(shù);
第二定位單元,用于根據(jù)所獲取的函數(shù)名和行數(shù),定位內(nèi)存泄露位置。
進(jìn)一步地,還包括:
定義模塊,用于定義兩組以上不同大小的內(nèi)存塊,其中,同一組內(nèi)的各內(nèi)存塊的大小一致;
放入模塊,用于將同一組的內(nèi)存塊按照預(yù)設(shè)的順序放入同一內(nèi)存池,并將所述內(nèi)存池的鏈表頭指針指向最后放入的內(nèi)存塊,將所述內(nèi)存池的鏈表尾指針指向最先放入的內(nèi)存塊;
連接模塊,用于將各內(nèi)存池的鏈表頭指針和鏈表尾指針通過(guò)數(shù)組進(jìn)行連接;
申請(qǐng)模塊,用于申請(qǐng)內(nèi)存時(shí),選擇內(nèi)存塊大小與所申請(qǐng)的內(nèi)存大小最接近的內(nèi)存池;
分配模塊,用于內(nèi)存塊分配時(shí),將所述內(nèi)存池中的第一個(gè)內(nèi)存塊作為被分配的內(nèi)存塊從鏈表中刪除,將所述內(nèi)存池中的第二個(gè)內(nèi)存塊的next指針指向空,將鏈表尾指針指向所述第二個(gè)內(nèi)存塊;
第一指向模塊,用于將被分配的內(nèi)存塊的next指針指向鏈表頭;
確定模塊,用于內(nèi)存塊釋放時(shí),根據(jù)其所指向的鏈表頭,確定對(duì)應(yīng)的內(nèi)存池;
第二指向模塊,用于將被釋放的內(nèi)存塊的next指針指向?qū)?yīng)的內(nèi)存池中的最后一個(gè)內(nèi)存塊,并將所述內(nèi)存池的鏈表頭指針指向所述內(nèi)存塊。
實(shí)施例一
本發(fā)明的實(shí)施例一為:一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位方法,主要對(duì)內(nèi)存池泄露和內(nèi)存越界進(jìn)行檢測(cè)并定位。
其中,如圖4所示,內(nèi)存池泄露的定位方法包括如下步驟:
s101:在內(nèi)存塊的頭部設(shè)置分配標(biāo)記、字符串指針和位置變量;
s102:若一內(nèi)存塊被分配,則將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)已分配的第一字符,將所述一內(nèi)存塊的字符串指針設(shè)置為申請(qǐng)所述一內(nèi)存塊的函數(shù)名,將所述一內(nèi)存塊的位置變量設(shè)置為申請(qǐng)所述一內(nèi)存塊的代碼所處的行數(shù);
s103:當(dāng)所述一內(nèi)存塊被釋放后,將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)未分配的第二字符;
s104:判斷內(nèi)存池的使用率是否超過(guò)預(yù)設(shè)的閾值,若是,則執(zhí)行步驟s105。
s105:獲取分配標(biāo)記為第二字符的內(nèi)存塊;
s106:根據(jù)所獲取的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存泄露位置。
其中,如圖5所示,所述步驟s106包括如下步驟:
s1061:獲取分配標(biāo)記為第二字符的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù);
s1062:獲取所述函數(shù)名和行數(shù)中出現(xiàn)次數(shù)最多的函數(shù)名和行數(shù);
s1063:根據(jù)所獲取的函數(shù)名和行數(shù),定位內(nèi)存泄露位置。
本實(shí)施例對(duì)于內(nèi)存池泄露定位,基于一個(gè)合理的假設(shè):內(nèi)存池泄露是在程序中某個(gè)位置申請(qǐng)了內(nèi)存,而沒(méi)有釋放,且沒(méi)有釋放的次數(shù)異常得多。在程序中,可能有非常多的位置申請(qǐng)了內(nèi)存,經(jīng)過(guò)一段處理后,在無(wú)bug存在的情況下,都會(huì)被釋放,即在正常運(yùn)行時(shí),未釋放的內(nèi)存數(shù)量是一個(gè)動(dòng)態(tài)穩(wěn)定的,比如正常運(yùn)行時(shí),內(nèi)存池中未釋放的內(nèi)存塊占比在60%以內(nèi)。而在發(fā)生內(nèi)存池泄露時(shí),可能達(dá)到100%,最后,發(fā)生無(wú)可分配內(nèi)存的情況。那么,在發(fā)生內(nèi)存泄露時(shí),40%的內(nèi)存是程序中某個(gè)位置申請(qǐng)了內(nèi)存,而沒(méi)有釋放。找出這40%的內(nèi)存是在哪個(gè)函數(shù)哪個(gè)位置申請(qǐng)的,就可以定位,即實(shí)現(xiàn)mtrace的功能(如果在時(shí)序要求不嚴(yán)格的情況下,用mtrace即可)。
因此,通過(guò)記錄申請(qǐng)內(nèi)存塊的函數(shù)及函數(shù)代碼位置,在內(nèi)存池泄露發(fā)生時(shí),查看沒(méi)有釋放的內(nèi)存塊中,哪個(gè)函數(shù)出現(xiàn)的次數(shù)異常多,即可確認(rèn)該函數(shù)發(fā)生了內(nèi)存泄露。
如圖6所示,內(nèi)存塊越界的定位方法包括如下步驟:
s201:在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值;
s202:若一內(nèi)存塊被分配,則將所述一內(nèi)存塊的字符串指針設(shè)置為申請(qǐng)所述一內(nèi)存塊的函數(shù)名,將所述一內(nèi)存塊的位置變量設(shè)置為申請(qǐng)所述一內(nèi)存塊的代碼所處的行數(shù);
s203:當(dāng)所述一內(nèi)存塊重新放入內(nèi)存池時(shí),分別檢測(cè)所述一內(nèi)存塊的第一標(biāo)記和第二標(biāo)記是否與預(yù)設(shè)的參數(shù)值一致;
s204:判斷所述一內(nèi)存塊的第一標(biāo)記是否與其預(yù)設(shè)的參數(shù)值一致且第二標(biāo)記與其預(yù)設(shè)的參數(shù)值不一致,若是,執(zhí)行步驟s205。
s205:判定所述一內(nèi)存塊越界;
s206:根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存越界的位置。
其中,如圖7所示,步驟s206包括如下步驟:
s2061:根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),獲取申請(qǐng)所述一內(nèi)存塊的第一代碼位置;
s2062:根據(jù)gdb或backtrace函數(shù)獲取函數(shù)棧信息;
s2063:根據(jù)所述函數(shù)棧信息,獲取釋放所述一內(nèi)存塊的第二代碼位置;
s2064:根據(jù)所述第一代碼位置和第二代碼位置,定位內(nèi)存越界的位置。
由于程序一般很大,所以在發(fā)生內(nèi)存越界時(shí)分析所有的代碼以找出bug位置很難,內(nèi)存塊越界定位的目標(biāo)是找出發(fā)生內(nèi)存越界時(shí)的那個(gè)位置即bug位置。內(nèi)存塊的越界定位一般是通過(guò)將出現(xiàn)bug的范圍縮小到一個(gè)很小的范圍,縮小的范圍越小則越好?,F(xiàn)有的定位內(nèi)存塊越界的方式是用mprotect將內(nèi)存頁(yè)設(shè)置成不可讀寫,其可以將越界范圍縮小到唯一的一個(gè)位置即bug位置,是目前最好的內(nèi)存塊越界定位方式。但在lte協(xié)議棧中,由于時(shí)序及內(nèi)存大小的限制(由于mprotect操作的最小單位是一個(gè)內(nèi)存頁(yè),即4k字節(jié)大小,內(nèi)存塊小于4k時(shí),內(nèi)存塊由2個(gè)內(nèi)存頁(yè)組成,13萬(wàn)個(gè)內(nèi)存塊就需要1g的內(nèi)存,一般嵌入式設(shè)備由于成本考慮,其內(nèi)存大小在滿足需求后不會(huì)有太多剩余,假設(shè)內(nèi)存塊平均大小100字節(jié)計(jì)算,用mprotect則需要8192字節(jié)即增加80倍的內(nèi)存),不能使用mprotect,所以,不能在發(fā)生內(nèi)存越界時(shí)馬上就能檢測(cè)到。
本實(shí)施例對(duì)于內(nèi)存塊越界的定位,通過(guò)設(shè)置在內(nèi)存塊頭部的第一標(biāo)記和尾部的第二標(biāo)記來(lái)判斷該內(nèi)存塊是否發(fā)生越界。例如,一個(gè)內(nèi)存池有4個(gè)物理上連續(xù)的內(nèi)存塊組成,順序依次為鏈表頭、內(nèi)存塊4、內(nèi)存塊3、內(nèi)存塊2、內(nèi)存塊1、鏈表尾;假設(shè)內(nèi)存塊大小均為8字節(jié),除內(nèi)存塊4外,其他內(nèi)存塊均被分配出去;程序在使用內(nèi)存塊3時(shí),使用了20字節(jié),則會(huì)將連續(xù)的內(nèi)存給改寫了,即內(nèi)存越界,內(nèi)存塊3越界,導(dǎo)致內(nèi)存塊1和內(nèi)存塊2的內(nèi)容被改寫(例如,改寫為0)。
如果內(nèi)存塊1先釋放,在放入內(nèi)存池時(shí),檢測(cè)到其第一標(biāo)記錯(cuò)誤(即與其預(yù)設(shè)的參數(shù)值不一致),而第二標(biāo)記正確(即與其預(yù)設(shè)的參數(shù)值一致),說(shuō)明雖然內(nèi)存塊1發(fā)生了內(nèi)存越界,但不是它引起的,所以忽略此內(nèi)存越界(既不處理,也不放入內(nèi)存池,因?yàn)榇藭r(shí)它的頭部信息已經(jīng)不可信任)。
如果內(nèi)存塊2先于內(nèi)存塊3被釋放,在放入內(nèi)存池時(shí),檢測(cè)到其第一標(biāo)記和第二標(biāo)記都是錯(cuò)誤的,說(shuō)明也不是它造成的越界。
內(nèi)存塊3使用完后,放入鏈表時(shí),檢測(cè)到其第一標(biāo)記正確(說(shuō)明前面的內(nèi)存塊沒(méi)有越界,即內(nèi)存塊4沒(méi)有越界,是正常的),而第二標(biāo)記錯(cuò)誤,說(shuō)明就是它發(fā)生了越界,此時(shí)使用gdb或者backtrace函數(shù),定位發(fā)生內(nèi)存越界后釋放此內(nèi)存塊的位置,并結(jié)合內(nèi)存池泄露定位方法加入的信息定位此內(nèi)存塊分配時(shí)的位置,即定位線索的頭尾,由此即可定位到bug位置,其余一般在代碼上即可排除(例如,某些位置只操作了此內(nèi)存塊的第1個(gè)字節(jié),那么,內(nèi)存越界肯定和它是無(wú)關(guān)的,可排除)。
根據(jù)上述內(nèi)存池泄露的定位方法和內(nèi)存塊越界的定位方法,可以得知,在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、分配標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值,即可同時(shí)對(duì)內(nèi)存池泄露和內(nèi)存塊越界進(jìn)行定位;具體地,內(nèi)存塊的示意圖如圖8所示,其中,magic1為第一標(biāo)記,magic1為第二標(biāo)記;alloced為分配標(biāo)記;表示該內(nèi)存塊是否已分配的flag;next為內(nèi)存塊原有的指針,在內(nèi)存塊空閑時(shí)指向下一個(gè)空閑節(jié)點(diǎn),在內(nèi)存塊被分配時(shí)指向內(nèi)存池;char*為字符串指針,用于指向申請(qǐng)?jiān)搩?nèi)存塊的函數(shù)的函數(shù)名字符串;int為位置變量,表示申請(qǐng)?jiān)搩?nèi)存塊的代碼在程序中所處的行數(shù);其中,第一標(biāo)記一定位于內(nèi)存塊最頭部的位置,第二標(biāo)記一定位于內(nèi)存塊最末尾的位置,分配標(biāo)記、字符串指針和位置變量之間的順序可互相調(diào)換。
本實(shí)施例通過(guò)在內(nèi)存塊中加入記錄該內(nèi)存中分配狀態(tài)的分配標(biāo)記,以及記錄申請(qǐng)?jiān)搩?nèi)存塊的函數(shù)名和函數(shù)位置的字符串指針和位置變量,即可在內(nèi)存泄露,即內(nèi)存池中超過(guò)預(yù)設(shè)個(gè)數(shù)的內(nèi)存塊都處于分配狀態(tài)時(shí),快速地定位出內(nèi)存泄露的位置;同時(shí),在內(nèi)存塊的頭尾分別加入第一標(biāo)記和第二標(biāo)記,可在內(nèi)存塊釋放時(shí),通過(guò)檢測(cè)第一標(biāo)記和第二標(biāo)記來(lái)判斷該內(nèi)存塊是否發(fā)生越界,定位到發(fā)生越界的內(nèi)存塊,再根據(jù)該內(nèi)存塊所記錄的函數(shù)名和函數(shù)位置,定位到內(nèi)存越界的具體位置;可在滿足lte嚴(yán)格時(shí)序要求,不影響協(xié)議棧正常工作的情況下(每毫秒增加耗時(shí)1微妙以內(nèi),即影響在千分之1以內(nèi))解決內(nèi)存池的內(nèi)存泄露及內(nèi)存越界問(wèn)題。
實(shí)施例二
請(qǐng)參照?qǐng)D9,本實(shí)施例是實(shí)施例一的進(jìn)一步拓展。步驟s101和s201之前還包括如下步驟:
s001:定義兩組以上不同大小的內(nèi)存塊,其中,同一組內(nèi)的各內(nèi)存塊的大小一致;例如,定義三組內(nèi)存塊,大小分別為8字節(jié)、16字節(jié)和32字節(jié),其中,第一組中的內(nèi)存塊的大小均為8字節(jié),第二組中的內(nèi)存塊的大小均為16字節(jié),第三組中的內(nèi)存塊的大小均為32字節(jié)。
s002:將同一組的內(nèi)存塊按照預(yù)設(shè)的順序放入同一內(nèi)存池,并將所述內(nèi)存池的鏈表頭指針指向最后放入的內(nèi)存塊,將所述內(nèi)存池的鏈表尾指針指向最先放入的內(nèi)存塊;此時(shí),可將第一組內(nèi)存塊放入的內(nèi)存池記為8字節(jié)內(nèi)存池,將第二組內(nèi)存塊放入的內(nèi)存池記為16字節(jié)內(nèi)存池,將第三組內(nèi)存塊放入的內(nèi)存池記為32字節(jié)內(nèi)存池。
s003:將各內(nèi)存池的鏈表頭指針和鏈表尾指針通過(guò)數(shù)組進(jìn)行連接;此時(shí)得到的內(nèi)存池結(jié)構(gòu)如圖10所示。
s004:申請(qǐng)內(nèi)存時(shí),選擇內(nèi)存塊大小與所申請(qǐng)的內(nèi)存大小最接近的內(nèi)存池;進(jìn)一步地,選擇內(nèi)存塊大小大于所申請(qǐng)的內(nèi)存大小且內(nèi)存塊大小與所申請(qǐng)的內(nèi)存大小最接近的內(nèi)存池;例如,所申請(qǐng)的內(nèi)存大小為15字節(jié)時(shí),則選擇16字節(jié)內(nèi)存池,而不選擇32字節(jié)內(nèi)存池;當(dāng)所申請(qǐng)的內(nèi)存大小為20字節(jié),即使與16字節(jié)接近,但由于16字節(jié)小于20字節(jié),因此需選擇32字節(jié)內(nèi)存池。
s005:內(nèi)存塊分配時(shí),將所述內(nèi)存池中的第一個(gè)內(nèi)存塊作為被分配的內(nèi)存塊從鏈表中刪除,將所述內(nèi)存池中的第二個(gè)內(nèi)存塊的next指針指向空,將鏈表尾指針指向所述第二個(gè)內(nèi)存塊;
s006:將被分配的內(nèi)存塊的next指針指向鏈表頭;此時(shí),該內(nèi)存池中內(nèi)存塊分配的示意圖如圖11所示。
s007:內(nèi)存塊釋放時(shí),根據(jù)其所指向的鏈表頭,確定對(duì)應(yīng)的內(nèi)存池;
s008:將被釋放的內(nèi)存塊的next指針指向?qū)?yīng)的內(nèi)存池中的最后一個(gè)內(nèi)存塊,并將所述內(nèi)存池的鏈表頭指針指向所述內(nèi)存塊。此時(shí),該內(nèi)存池中內(nèi)存塊釋放的結(jié)構(gòu)示意圖如圖12所述。
本實(shí)施例對(duì)內(nèi)存池的操作,只有改變2-4個(gè)鏈表指針的操作,如果是多線程,則需要加鎖和解鎖操作,因此本實(shí)施例有效地提高了內(nèi)存池的處理效率。
實(shí)施例三
本實(shí)施例是對(duì)應(yīng)上述實(shí)施例的一具體應(yīng)用場(chǎng)景。本實(shí)施例以圖8所示的內(nèi)存塊為例。
請(qǐng)參照?qǐng)D13,在分配前,char*和int位置無(wú)任何有效內(nèi)容,alloced標(biāo)記設(shè)置為0x22(表示未分配)。內(nèi)存被分配后,alloced標(biāo)記設(shè)置為0x11(表示已分配),char*和int位置存入的是調(diào)用函數(shù)名和位置。在釋放后,alloced再次設(shè)置為0x22。其中有memleak變量指向的內(nèi)存塊出現(xiàn)了內(nèi)存泄露,并未釋放。正常運(yùn)行時(shí),在內(nèi)存池中最多只會(huì)存在一個(gè)未釋放的addr0、memleak、addr1內(nèi)存塊,即在內(nèi)存池中,未釋放的內(nèi)存塊中,testfunc函數(shù)最多只會(huì)存在3個(gè)。但是,由于memleak變量申請(qǐng)內(nèi)存后,未釋放,多次執(zhí)行testfunc函數(shù)后,內(nèi)存池的泄露就會(huì)越來(lái)越嚴(yán)重,直到影響程序運(yùn)行。此時(shí),查看內(nèi)存池情況,如圖14所示,內(nèi)存池中總共由22個(gè)內(nèi)存塊組成,在正常運(yùn)行時(shí),最多只會(huì)出現(xiàn)3個(gè)內(nèi)存被使用,即正常情況下,內(nèi)存池的使用率是13%(3/22)。而在異常情況下,如圖中所示,有16個(gè)內(nèi)存被使用,即內(nèi)存池的使用率是72%,可以確定發(fā)生了內(nèi)存泄露。在發(fā)生泄露后,用gdb腳本(或者printf函數(shù)打印)將內(nèi)存池中所有未釋放的內(nèi)存塊中保存的函數(shù)名及位置打印出來(lái)即可發(fā)現(xiàn),“testfunc”位置14出現(xiàn)的次數(shù)是14次,“testfunc”位置13和15的次數(shù)各1次,可以判斷,“testfunc”位置14申請(qǐng)的內(nèi)存發(fā)生了泄露,即定位在“testfunc”的14行,實(shí)現(xiàn)mtrace的功能。
對(duì)于內(nèi)存塊越界定位,請(qǐng)參照?qǐng)D15,其申請(qǐng)了3個(gè)內(nèi)存塊,且剛好物理上連續(xù)。由于在申請(qǐng)時(shí)是申請(qǐng)8個(gè)字節(jié),而使用時(shí)是20個(gè)字節(jié),導(dǎo)致越界。在程序中,addr0先于addr1和addr2分配而最后釋放。在addr2釋放時(shí),檢測(cè)到第一標(biāo)記為0,是錯(cuò)誤的,而第二標(biāo)記是正確的,說(shuō)明在物理上連續(xù)的前面內(nèi)存塊發(fā)生了越界且越界到此內(nèi)存塊為止,不處理addr2指向的內(nèi)存塊(因?yàn)樗膎ext指針已損壞,不能指向正確的鏈表,所以不將其加入空閑內(nèi)存塊鏈表)。在addr1釋放時(shí),檢測(cè)到第一標(biāo)記和第二標(biāo)記的標(biāo)記都是錯(cuò)誤的,說(shuō)明是在物理上連續(xù)的前面內(nèi)存塊發(fā)生了越界且越界到此內(nèi)存塊以后,不處理addr1指向的內(nèi)存。
在addr0釋放時(shí),檢測(cè)到第一標(biāo)記是正確的,而第二標(biāo)記是錯(cuò)誤的,說(shuō)明此內(nèi)存塊發(fā)生了內(nèi)存越界,據(jù)此,根據(jù)gdb或者backtrace函數(shù)獲取函數(shù)棧信息,即可定位到testfunc函數(shù)中的26行,而根據(jù)保存在內(nèi)存塊的函數(shù)名和函數(shù)位置信息可知內(nèi)存申請(qǐng)是在testfunc函數(shù)的13行(如果沒(méi)有此信息,內(nèi)存塊釋放對(duì)應(yīng)的內(nèi)存塊申請(qǐng)位置可能有多個(gè),即不同函數(shù)不同位置申請(qǐng)的內(nèi)存塊,可能在同一個(gè)位置釋放),即內(nèi)存越界發(fā)生在testfunc的13行到26行之間的某個(gè)位置,而在這位置之間只有testfunc的18行對(duì)addr0進(jìn)行了操作,所以,就是它產(chǎn)生的內(nèi)存越界,修改testfunc的18行的bug即可解決這個(gè)內(nèi)存越界問(wèn)題。
本實(shí)施例對(duì)內(nèi)存池泄露和內(nèi)存塊越界的定位方法,都只需對(duì)幾個(gè)標(biāo)記進(jìn)行賦值和判斷,對(duì)性能的影響是可以忽略不計(jì)的。
實(shí)施例四
請(qǐng)參照?qǐng)D17,本實(shí)施例是對(duì)應(yīng)上述實(shí)施例的一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位系統(tǒng),包括:
第一設(shè)置模塊1,用于在內(nèi)存塊的頭部設(shè)置第一標(biāo)記、分配標(biāo)記、字符串指針和位置變量,在內(nèi)存塊的尾部設(shè)置第二標(biāo)記,所述第一標(biāo)記和第二標(biāo)記為預(yù)設(shè)的參數(shù)值;
第二設(shè)置模塊2,用于若一內(nèi)存塊被分配,則將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)已分配的第一字符,將所述一內(nèi)存塊的字符串指針設(shè)置為申請(qǐng)所述一內(nèi)存塊的函數(shù)名,將所述一內(nèi)存塊的位置變量設(shè)置為申請(qǐng)所述一內(nèi)存塊的代碼所處的行數(shù);
第三設(shè)置模塊3,用于當(dāng)所述一內(nèi)存塊被釋放后,將所述一內(nèi)存塊的分配標(biāo)記設(shè)置為預(yù)設(shè)的對(duì)應(yīng)未分配的第二字符;
檢測(cè)模塊4,用于當(dāng)所述一內(nèi)存塊重新放入內(nèi)存池時(shí),分別檢測(cè)所述一內(nèi)存塊的第一標(biāo)記和第二標(biāo)記是否與預(yù)設(shè)的參數(shù)值一致;
判定模塊5,用于若所述一內(nèi)存塊的第一標(biāo)記與其預(yù)設(shè)的參數(shù)值一致且第二標(biāo)記與其預(yù)設(shè)的參數(shù)值不一致,則判定所述一內(nèi)存塊越界;
第一定位模塊6,用于根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存越界的位置;
獲取模塊7,用于若內(nèi)存池的使用率超過(guò)預(yù)設(shè)的閾值,則獲取分配標(biāo)記為第二字符的內(nèi)存塊;
第二定位模塊8,用于根據(jù)所獲取的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),定位內(nèi)存泄露位置。
進(jìn)一步地,所述第一定位模塊6包括:
第一獲取單元61,用于根據(jù)所述一內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù),獲取申請(qǐng)所述一內(nèi)存塊的第一代碼位置;
第二獲取單元62,用于根據(jù)gdb或backtrace函數(shù)獲取函數(shù)棧信息;
第三獲取單元63,用于根據(jù)所述函數(shù)棧信息,獲取釋放所述一內(nèi)存塊的第二代碼位置;
第一定位單元64,用于根據(jù)所述第一代碼位置和第二代碼位置,定位內(nèi)存越界的位置。
進(jìn)一步地,所述第二定位模塊8包括:
第四獲取單元81,用于獲取分配標(biāo)記為第二字符的內(nèi)存塊的字符串指針記錄的函數(shù)名以及位置變量記錄的行數(shù);
第五獲取單元82,用于獲取所述函數(shù)名和行數(shù)中出現(xiàn)次數(shù)最多的函數(shù)名和行數(shù);
第二定位單元83,用于根據(jù)所獲取的函數(shù)名和行數(shù),定位內(nèi)存泄露位置。
進(jìn)一步地,還包括:
定義模塊9,用于定義兩組以上不同大小的內(nèi)存塊,其中,同一組內(nèi)的各內(nèi)存塊的大小一致;
放入模塊10,用于將同一組的內(nèi)存塊按照預(yù)設(shè)的順序放入同一內(nèi)存池,并將所述內(nèi)存池的鏈表頭指針指向最后放入的內(nèi)存塊,將所述內(nèi)存池的鏈表尾指針指向最先放入的內(nèi)存塊;
連接模塊11,用于將各內(nèi)存池的鏈表頭指針和鏈表尾指針通過(guò)數(shù)組進(jìn)行連接;
申請(qǐng)模塊12,用于申請(qǐng)內(nèi)存時(shí),選擇內(nèi)存塊大小與所申請(qǐng)的內(nèi)存大小最接近的內(nèi)存池;
分配模塊13,用于內(nèi)存塊分配時(shí),將所述內(nèi)存池中的第一個(gè)內(nèi)存塊作為被分配的內(nèi)存塊從鏈表中刪除,將所述內(nèi)存池中的第二個(gè)內(nèi)存塊的next指針指向空,將鏈表尾指針指向所述第二個(gè)內(nèi)存塊;
第一指向模塊14,用于將被分配的內(nèi)存塊的next指針指向鏈表頭;
確定模塊15,用于內(nèi)存塊釋放時(shí),根據(jù)其所指向的鏈表頭,確定對(duì)應(yīng)的內(nèi)存池;
第二指向模塊16,用于將被釋放的內(nèi)存塊的next指針指向?qū)?yīng)的內(nèi)存池中的最后一個(gè)內(nèi)存塊,并將所述內(nèi)存池的鏈表頭指針指向所述內(nèi)存塊。
綜上所述,本發(fā)明提供的一種基于lte協(xié)議棧的內(nèi)存池問(wèn)題定位方法及其系統(tǒng),通過(guò)在內(nèi)存塊中加入記錄該內(nèi)存中分配狀態(tài)的分配標(biāo)記,以及記錄申請(qǐng)?jiān)搩?nèi)存塊的函數(shù)名和函數(shù)位置的字符串指針和位置變量,即可在內(nèi)存泄露,即內(nèi)存池中超過(guò)預(yù)設(shè)個(gè)數(shù)的內(nèi)存塊都處于分配狀態(tài)時(shí),快速地定位出內(nèi)存泄露的位置;同時(shí),在內(nèi)存塊的頭尾分別加入第一標(biāo)記和第二標(biāo)記,可在內(nèi)存塊釋放時(shí),通過(guò)檢測(cè)第一標(biāo)記和第二標(biāo)記來(lái)判斷該內(nèi)存塊是否發(fā)生越界,定位到發(fā)生越界的內(nèi)存塊,再根據(jù)該內(nèi)存塊所記錄的函數(shù)名和函數(shù)位置,定位到內(nèi)存越界的具體位置;本發(fā)明可在滿足lte嚴(yán)格時(shí)序要求,不影響協(xié)議棧正常工作的情況下(每毫秒增加耗時(shí)1微妙以內(nèi),即影響在千分之1以內(nèi))解決內(nèi)存池的內(nèi)存泄露及內(nèi)存越界問(wèn)題。
以上所述僅為本發(fā)明的實(shí)施例,并非因此限制本發(fā)明的專利范圍,凡是利用本發(fā)明說(shuō)明書及附圖內(nèi)容所作的等同變換,或直接或間接運(yùn)用在相關(guān)的技術(shù)領(lǐng)域,均同理包括在本發(fā)明的專利保護(hù)范圍內(nèi)。