TBOX的內存分配在調試模式下,可以檢測支持內存洩露和越界,而且還能精確定位到出問題的那塊內存具體分配位置,和函數調用堆棧。
1. 內存洩露檢測
內存洩露的檢測必須在程序退出的前一刻,調用tb_exit()的時候,才會執行,如果有洩露,會有詳細輸出到終端上。
tb_void_t tb_demo_leak() { tb_pointer_t data = tb_malloc0(10); }
輸出: [tbox]: [error]: leak: 0x7f9d5b058908 at tb_static_fixed_pool_dump(): 735, memory/impl/static_fixed_pool.c [tbox]: [error]: data: from: tb_demo_leak(): 43, memory/check.c [tbox]: [error]: [0x000001050e742a]: 0 demo.b 0x00000001050e742a tb_fixed_pool_malloc0_ + 186 [tbox]: [error]: [0x000001050f972b]: 1 demo.b 0x00000001050f972b tb_small_pool_malloc0_ + 507 [tbox]: [error]: [0x000001050f593c]: 2 demo.b 0x00000001050f593c tb_pool_malloc0_ + 540 [tbox]: [error]: [0x00000105063cd7]: 3 demo.b 0x0000000105063cd7 tb_demo_leak + 55 [tbox]: [error]: [0x00000105063e44]: 4 demo.b 0x0000000105063e44 tb_demo_memory_check_main + 20 [tbox]: [error]: [0x0000010505b08e]: 5 demo.b 0x000000010505b08e main + 878 [tbox]: [error]: [0x007fff8c95a5fd]: 6 libdyld.dylib 0x00007fff8c95a5fd start + 1 [tbox]: [error]: [0x00000000000002]: 7 ??? 0x0000000000000002 0x0 + 2 [tbox]: [error]: data: 0x7f9d5b058908, size: 10, patch: cc
2. 內存越界檢測
越界溢出的檢測,是實時完成的,而且對libc也做了插樁,所以對常用strcpy,memset等的使用,都回去檢測
tb_void_t tb_demo_overflow() { tb_pointer_t data = tb_malloc0(10); if (data) { tb_memset(data, 0, 11); tb_free(data); } }
輸出: [tbox]: [memset]: [overflow]: [0x0 x 11] => [0x7f950b044508, 10] [tbox]: [memset]: [overflow]: [0x0000010991a1c7]: 0 demo.b 0x000000010991a1c7 tb_memset + 151 [tbox]: [memset]: [overflow]: [0x000001098a2d01]: 1 demo.b 0x00000001098a2d01 tb_demo_overflow + 97 [tbox]: [memset]: [overflow]: [0x000001098a3044]: 2 demo.b 0x00000001098a3044 tb_demo_memory_check_main + 20 [tbox]: [memset]: [overflow]: [0x0000010989a28e]: 3 demo.b 0x000000010989a28e main + 878 [tbox]: [memset]: [overflow]: [0x007fff8c95a5fd]: 4 libdyld.dylib 0x00007fff8c95a5fd start + 1 [tbox]: [memset]: [overflow]: [0x00000000000002]: 5 ??? 0x0000000000000002 0x0 + 2 [tbox]: [malloc]: [from]: data: from: tb_demo_overflow(): 12, memory/check.c [tbox]: [malloc]: [from]: [0x0000010992662a]: 0 demo.b 0x000000010992662a tb_fixed_pool_malloc0_ + 186 [tbox]: [malloc]: [from]: [0x0000010993892b]: 1 demo.b 0x000000010993892b tb_small_pool_malloc0_ + 507 [tbox]: [malloc]: [from]: [0x00000109934b3c]: 2 demo.b 0x0000000109934b3c tb_pool_malloc0_ + 540 [tbox]: [malloc]: [from]: [0x000001098a2cd7]: 3 demo.b 0x00000001098a2cd7 tb_demo_overflow + 55 [tbox]: [malloc]: [from]: [0x000001098a3044]: 4 demo.b 0x00000001098a3044 tb_demo_memory_check_main + 20 [tbox]: [malloc]: [from]: [0x0000010989a28e]: 5 demo.b 0x000000010989a28e main + 878 [tbox]: [malloc]: [from]: [0x007fff8c95a5fd]: 6 libdyld.dylib 0x00007fff8c95a5fd start + 1 [tbox]: [malloc]: [from]: [0x00000000000002]: 7 ??? 0x0000000000000002 0x0 + 2 [tbox]: [malloc]: [from]: data: 0x7f950b044508, size: 10, patch: cc [tbox]: [malloc]: [from]: data: first 10-bytes: [tbox]: =================================================================================================================================================== [tbox]: 00000000 00 00 00 00 00 00 00 00 00 00 .......... [tbox]: [error]: abort at tb_memset(): 255, libc/string/memset.c
3. 內存重疊覆蓋檢測
如果兩塊內存的copy發生了重疊,有可能會覆蓋掉部分數據,導致bug,因此TBOX對此也做了些檢測。
tb_void_t tb_demo_overlap() { tb_pointer_t data = tb_malloc(10); if (data) { tb_memcpy(data, (tb_byte_t const*)data + 1, 5); tb_free(data); } }
輸出 [tbox]: [memcpy]: [overlap]: [0x7fe9b5042509, 5] => [0x7fe9b5042508, 5] [tbox]: [memcpy]: [overlap]: [0x000001094403b8]: 0 demo.b 0x00000001094403b8 tb_memcpy + 632 [tbox]: [memcpy]: [overlap]: [0x000001093c99f9]: 1 demo.b 0x00000001093c99f9 tb_demo_overlap + 105 [tbox]: [memcpy]: [overlap]: [0x000001093c9a44]: 2 demo.b 0x00000001093c9a44 tb_demo_memory_check_main + 20 [tbox]: [memcpy]: [overlap]: [0x000001093c0c8e]: 3 demo.b 0x00000001093c0c8e main + 878 [tbox]: [memcpy]: [overlap]: [0x007fff8c95a5fd]: 4 libdyld.dylib 0x00007fff8c95a5fd start + 1 [tbox]: [memcpy]: [overlap]: [0x00000000000002]: 5 ??? 0x0000000000000002 0x0 + 2 [tbox]: [malloc]: [from]: data: from: tb_demo_overlap(): 58, memory/check.c [tbox]: [malloc]: [from]: [0x0000010945eadb]: 0 demo.b 0x000000010945eadb tb_small_pool_malloc_ + 507 [tbox]: [malloc]: [from]: [0x0000010945b23c]: 1 demo.b 0x000000010945b23c tb_pool_malloc_ + 540 [tbox]: [malloc]: [from]: [0x000001093c99c7]: 2 demo.b 0x00000001093c99c7 tb_demo_overlap + 55 [tbox]: [malloc]: [from]: [0x000001093c9a44]: 3 demo.b 0x00000001093c9a44 tb_demo_memory_check_main + 20 [tbox]: [malloc]: [from]: [0x000001093c0c8e]: 4 demo.b 0x00000001093c0c8e main + 878 [tbox]: [malloc]: [from]: [0x007fff8c95a5fd]: 5 libdyld.dylib 0x00007fff8c95a5fd start + 1 [tbox]: [malloc]: [from]: [0x00000000000002]: 6 ??? 0x0000000000000002 0x0 + 2 [tbox]: [malloc]: [from]: data: 0x7fe9b5042508, size: 10, patch: cc [tbox]: [malloc]: [from]: data: first 10-bytes: [tbox]: =================================================================================================================================================== [tbox]: 00000000 CC CC CC CC CC CC CC CC CC CC .......... [tbox]: [error]: abort at tb_memcpy(): 125, libc/string/memcpy.c
4. 內存雙重釋放檢測
tb_void_t tb_demo_free2() { tb_pointer_t data = tb_malloc0(10); if (data) { tb_free(data); tb_free(data); } }
輸出 [tbox]: [assert]: expr[((impl->used_info)[(index) >> 3] & (0x1 << ((index) & 7)))]: double free data: 0x7fd93386c708 at tb_static_fixed_pool_free(): 612, memory/impl/static_fixed_pool.c [tbox]: [0x0000010c9f553c]: 0 demo.b 0x000000010c9f553c tb_static_fixed_pool_free + 972 [tbox]: [0x0000010c9ee7a9]: 1 demo.b 0x000000010c9ee7a9 tb_fixed_pool_free_ + 713 [tbox]: [0x0000010ca01ff5]: 2 demo.b 0x000000010ca01ff5 tb_small_pool_free_ + 885 [tbox]: [0x0000010c9fdb4f]: 3 demo.b 0x000000010c9fdb4f tb_pool_free_ + 751 [tbox]: [0x0000010c96ac8e]: 4 demo.b 0x000000010c96ac8e tb_demo_free2 + 158 [tbox]: [0x0000010c96ae44]: 5 demo.b 0x000000010c96ae44 tb_demo_memory_check_main + 20 [tbox]: [0x0000010c96208e]: 6 demo.b 0x000000010c96208e main + 878 [tbox]: [0x007fff8c95a5fd]: 7 libdyld.dylib 0x00007fff8c95a5fd start + 1 [tbox]: [0x00000000000002]: 8 ??? 0x0000000000000002 0x0 + 2 [tbox]: [error]: free(0x7fd93386c708) failed! at tb_demo_free2(): 37, memory/check.c at tb_static_fixed_pool_free(): 649, memory/impl/static_fixed_pool.c [tbox]: [error]: data: from: tb_demo_free2(): 33, memory/check.c [tbox]: [error]: [0x0000010c9ee42a]: 0 demo.b 0x000000010c9ee42a tb_fixed_pool_malloc0_ + 186 [tbox]: [error]: [0x0000010ca0072b]: 1 demo.b 0x000000010ca0072b tb_small_pool_malloc0_ + 507 [tbox]: [error]: [0x0000010c9fc93c]: 2 demo.b 0x000000010c9fc93c tb_pool_malloc0_ + 540 [tbox]: [error]: [0x0000010c96ac27]: 3 demo.b 0x000000010c96ac27 tb_demo_free2 + 55 [tbox]: [error]: [0x0000010c96ae44]: 4 demo.b 0x000000010c96ae44 tb_demo_memory_check_main + 20 [tbox]: [error]: [0x0000010c96208e]: 5 demo.b 0x000000010c96208e main + 878 [tbox]: [error]: [0x007fff8c95a5fd]: 6 libdyld.dylib 0x00007fff8c95a5fd start + 1 [tbox]: [error]: [0x00000000000002]: 7 ??? 0x0000000000000002 0x0 + 2 [tbox]: [error]: data: 0x7fd93386c708, size: 10, patch: cc [tbox]: [error]: data: first 10-bytes: [tbox]: =================================================================================================================================================== [tbox]: 00000000 00 00 00 00 00 00 00 00 00 00 .......... [tbox]: [error]: abort at tb_static_fixed_pool_free(): 655, memory/impl/static_fixed_pool.c
這個軟件的測試原理就是不停地對內存進行讀寫,從而發現內存中存在錯誤的區域。雖然是內存測試軟件,不過它也挺考驗CPU的,當你運行它的時候你會發現被這個軟件占用的那個CPU核心(如果你電腦是多核心的話)占用率直接到了百分之百。這樣看來,如果你的電腦是單核心的那就只運行一個MEMTEST好了,運行得多了也快不了多少。如果你的電腦是多核心的那就多開一個,我個人覺得處理器是幾個核心的就同時運行幾個效率比較高。當你只運行一個的時候內存大小就直接設為你的物理內存大小就可以了,比如你的768MB。再順便提一下,有時會碰到無法分配內存的情況,那就開兩個測試程序,然後將測試內存大小填小一點。如果你的電腦是雙核甚至是多核心的那就多開幾個同時測試,這樣每個測試程序可以少分一點測試內存,效率會高些。一般來說開幾個程序就把內存平均分成幾分進行測試,這樣既能保證完全測試了內存又兼顧了速度。例如你運行了三個MEMTEST程序,那就把你的內存分成三份,每個程序分配256MB的內存進行測試。要注意的是不管你運行幾個MEMTEST,在所有的測試程序上分配的內存總和可以比物理內存大小稍大一些,但不要大太多,否則它會連虛擬內存也進行測試,這個卻不是我們需要的。開始測試後就不要管它了,如果碰到內存讀寫錯誤它就會報錯。測試時間一般推薦至少在20分鐘以上,也不那麼絕對,測試時間當然還會跟內存大小和讀寫速度有關了。軟件下面有個進度指示,用百分比表示,代表你所分配的內存測試完多少。我覺得至少要讓每個程序都達到200%以上,也就是說將內存測試完兩遍。尤其是連一遍都沒測試完的時候,可別急著下內存正常的結論。
內存診斷測試狀態有兩種模式,17項測試,如256M內存,全程約一小時;
一、extended tests擴展內存測試模式,有6項測試,它是不斷循環的,只須測試一Pass就可,當顯示Pass:2時,可按“T”鍵進入另一個模式.
擴展內存測試模式分別檢測:MATS+,INVC,LRAND,STRIDE6,WMATS+,WINVC
二、standard tests標准內存測試模式,有11項測試,它也是不斷循環的,只須測試一Pass就可,當顯示Pass:2時,可按“T”鍵進入另一個模式,也可按“X”鍵,退出,完成測試。
全程總共17項測試,只要其中一項不能Succeeded,如果你的內存是兩條或以上,可轉換一下內存的排列順序再試,一定要全部Succeeded,否則就要換內存了(或者是內存槽壞了),如果在測試過程中死機,那說明你的CPU有問題或超頻過頭了。
Succeeded=成功 Active=活躍 都表示沒問題
STANDARD 模式測試內容:MATS+,INVC,LRAND,STRIDE6,WMATS+,WINVC,MATS+,STRIDE38,WSTRIDE-6,ERAND(時間較長),後面應該還有個沒記下來。
注意:這個軟件是不會自動停止的,可以按X退出 用的時候多看看它的數據
內存檢測的軟件英文注解
pass progress 通過進程
test progress 測試進程
ran progress 執行進程
MATS+ succeeded MATS+成功
INVC
STRIDE6
WMATS+
WINVC
LRAND active LRAND 活躍(的進程)
內存診斷測試狀態有兩種模式,17項測試,如256M內存,全程約一小時;
一、extended tests擴展內存測試模式,有6項測試,它是不斷循環的,只須測試一Pass就可,當顯示Pass:2時,可按“T”鍵進
入另一個模式:
二、standard tests標准內存測試模式,有11項測試,它也是不斷循環的,只須測試一Pass就可,當顯示Pass:2時,可按“T”
鍵進入另一個模式,也可按“X”鍵,退出,完成測試。
全程總共17項測試,只要其中一項不能Succeeded,如果你的內存是兩條或以上,可轉換一下內存的排列順序再試,一定要全
部Succeeded,否則就要換內存了(或者是內存槽壞了),如果在測試過程中死機,那說明你的CPU有問題或超頻過頭了。
Succeeded=成功 Active=活躍 都表示沒問題
注意:這個軟件是不會自動停止的,可以按X退出 用的時候多看看它的數據