robot
最新文章(10)
Mqskit 和其它相關工具
CPython 的 GC 二、三事
寫 Mecurial Extension 是件快樂的事!
Mozilla 台灣辨公室徵人啟事
關於 Apple 的兩項專利
core dump 之前的 frame
怎麼發出 beep 聲?
先承認你要找的是奴才吧!
程式碼要清的多乾淨?
FreeBSD 的 Thread-Local Storage 實作
首頁
新編
最新留言
Entries RSS
重要關鍵字(10)
coding (122)
Python (93)
FreeBSD (71)
WEB (61)
URL (48)
hardware (46)
javascript (36)
Linux (34)
blog (30)
C++ (16)
所有關鍵字
新增 URL
解決 memory leak in FreeBSD
by thinker
2 Columns
關鍵字:
coding
FreeBSD
memory leak 是 $C$/$C++$ programmer 最常遇到的問題之一,其來自於 $C$/$C++$ 並沒有內建 GC ,所有動態配置的記憶體,都必需由 programmer 自行管理。於是在人腦的不完美之下,經常有些記憶體忘了被釋放,使程式使用的記憶空間,隨時間的增長。 memory leak 是極難測知的,往往是在程式用光系統記憶體時,programmer 才有警覺。 $FreeBSD$ 的 $C$ library ,提供動態配置記憶體的使用報告,能讓 programmer 在程式結束時,得到結束時的使用狀態。透過這個功能,我們可以觀察有多少記憶體被使用,從而得知 memory leak 的使用狀況。 memory 使用報告的啟動方式是,設定 environment variable MALLOC_OPTIONS=P 。 $C$ library 在程式結束時,會檢查這個變數,從而列印出記憶體的使用報告。 例如,有一個程式 $test$.c 如下: {{{#!cpp #include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv[]) { char *buf; int i; for(i = 0; i < 10; i++) { buf = (char *)malloc(128); if(i % 2) free(buf); } } }}} 執行時,我們可以得到報告如下: {{{ tmp$$ MALLOC_OPTIONS=P ./$test$ ___ Begin malloc statistics ___ Number of CPUs: 1 Number of arenas: 1 Chunk size: 2097152 (2^21) Quantum size: 16 (2^4) Max small size: 512 Pointer size: 4 Assertions enabled Allocated: 640, space used: 2097152 base: total 1796276 chunks: nchunks highchunks curchunks 1 1 1 huge: nmalloc ndalloc allocated 0 0 0 arenas[0] statistics: allocated: 640 calls: nmalloc ndalloc nmadvise 10 5 0 large requests: 0 bins: bin size nregs run_sz nrequests nruns hiruns curruns npromo ndemo [0..9] 10 Q 128 509 65536 10 1 1 1 0 0 [11..36] --- End malloc statistics --- }}} 在這個程式中, allocate 10 次 128 大小的記憶體,但只有其中 5 次被 free 。因此,在最後程式結束時,應該有 128 * 5 = 640 bytes 的記憶體沒被釋放。第 9 行的 ```Allocated: 640''' 即是指系統最後使用的記憶體量為 640 bytes 。 == 不歸零的原因 == 一個沒有 memory leak 的程式,應該在結束時,將所有的 memory 全都釋放掉, Allocated 應該歸零。但有時侯並不是這樣。例如: {{{#!cpp #include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv[]) { printf("hello %s\n", "world"); } }}} 照理應該歸零,但事實上並不是 {{{ tmp$$ MALLOC_OPTIONS=P ./$test$ hello world ___ Begin malloc statistics ___ Number of CPUs: 1 Number of arenas: 1 Chunk size: 2097152 (2^21) Quantum size: 16 (2^4) Max small size: 512 Pointer size: 4 Assertions enabled Allocated: 4096, space used: 2097152 [........ skipped ........] }}} 系統還留有 4Kbytes 的空間沒被釋放,但我們明明沒使用任何動態配置記憶體。這是由 printf 所造成的, printf 會自行配置一塊空間重複使用。因此,最後會留下這一段空間。同樣的情況,也可能發生在其它的 library 裡,因此我們並不以使用空間歸零作為判斷依據。 == 重複次數 == 小弟使用的方法,是將要測試的程式碼,以 for loop 重複 N 次和 K 次, N != K 。雖然一些 library 可能會配置一些空間。但重複 N 次和 K 次後,最後留下末釋放的空間,應該是相同的。若不相同,那表示有 memory leak 發生。 例如: {{{#!cpp #include <stdio.h> #include <stdlib.h> #define N 100 int main(int argc, const char *argv[]) { char *buf; int i; printf("hello %s\n", "world"); for(i = 0; i < N; i++) { buf = (char *)malloc(256); free(buf); } } }}} 不論 N 是 100 或者 1000 ,得到的結果應該是一樣的: {{{ tmp$$ MALLOC_OPTIONS=P ./$test$ hello world ___ Begin malloc statistics ___ Number of CPUs: 1 Number of arenas: 1 Chunk size: 2097152 (2^21) Quantum size: 16 (2^4) Max small size: 512 Pointer size: 4 Assertions enabled Allocated: 4096, space used: 2097152 [...... skipped ......] }}} == 最後 == 透過 unit $test$ 和記憶體使用報告, $FreeBSD$ 能很容易得知記憶體的使用狀況,並偵測 memory leak 的情況。對 $C$/$C++$ 的 programmer 而言,最好能為每一個 module 進行 unit $test$ ,進而確定沒有 memory leak 發生,以免在未來造成更大的記憶體災難。
最後更新時間: 2007-05-31 10:33:33 CST |
引用
查詢:
COMMENTS: