robot
最新文章(10)
MadButterfly 和 Javascript 合體的威力
Adapt C code for Javascript
OpenVG for Linux/FreeBSD with X
回收 Linux cached memory
公告: 更換 domain name
關於 GCC nested function
GLUT 作為 Embedded System 的 UI 平台
別被 kernel 嚇到了
SVG 加 Gecko 完全攻略
在 OSDC 展示的 Plurk client
首頁
新編
最新留言
Entries RSS
重要關鍵字(10)
coding (120)
Python (93)
FreeBSD (71)
WEB (61)
URL (48)
hardware (46)
雜記 (45)
javascript (36)
Linux (31)
blog (30)
所有關鍵字
新增 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: