<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yoichi Kawasaki&#039;s Web &#187; gc</title>
	<atom:link href="http://yk55.com/blog/tags/gc/feed/" rel="self" type="application/rss+xml" />
	<link>http://yk55.com/blog</link>
	<description>my publicly accessible private memorandums</description>
	<lastBuildDate>Mon, 14 May 2012 01:31:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
	<!-- google_ad_section_end --><!-- google_ad_section_start(weight=ignore) -->	<item>
		<title>簡単Boehm GCによるC/C++メモリリーク検知</title>
		<link>http://yk55.com/blog/2010/03/25/boehm_gc_detect_memory_leak/</link>
		<comments>http://yk55.com/blog/2010/03/25/boehm_gc_detect_memory_leak/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 14:37:54 +0000</pubDate>
		<dc:creator>yoichi</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[boehm]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[cplusplus]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[gc]]></category>

		<guid isPermaLink="false">http://yk55.com/blog/?p=269</guid>
		<description><![CDATA[Boehm GCはガベージコレクションの標準実装がないC/C++でガベージコレクションのようなことを実現可能にしてくれるライブラリ。 一度確保されたリソースは明示的に解放処理が行われない限りメモリリークが発生してしまうけれどもBoehm GCで用意されている関数群（通常はGC_MALLOC）を使ってリソースを確保すれば不要になった段階で自動的に解放してくれる。 ソースコード全体で統一してこのライブラリを利用していればオブジェクトの寿命管理の手間は減るだろうし自分がコードの責任者であるならば難しいところを枯れたライブラリにお任せできるので安心感はあるのだろう。ちなみにこのライブラリ、以前からその存在は知ってはいたけれどスマートポインタ派の自分としてはオブジェクトの寿命管理のためにこれを使うモチベーションはいまいち感じられない。 そんなBoehm GCは「Using the Garbage Collector as Leak Detector」で紹介されているようにメモリリーク検知用ユーティリティとしても使える。ドキュメントやソースコードを覗いてみて少し工夫すれば手軽に既存のコードに殆ど手を加えること無くメモリリークの検知ができそうだったので試しにサンプルコードを書いてみた。以下、Boehm GCのインストールからC/C++コードでのメモリリーク検知について。 Boehm GCインストール まずは自分の環境(debina5.0.1&#8243;lenny&#8221;)にBoehm GCをインストールしてみる。 Boehm GCライブラリをつかって開発するにはlibgc-devとlibgc1c2が必要。もし自分の環境に合うパッケージが存在しない場合は直接ここから tar.gzボールをダウンロードして例のconfigure、make、make install。 $ sudo apt-get install libgc-dev $ sudo apt-get install libgc1c2 $ dpkg --list &#124;grep libgc ii &#160;libgc-dev &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; 1:6.8-1.1 &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">Boehm GC</a>はガベージコレクションの標準実装がないC/C++でガベージコレクションのようなことを実現可能にしてくれるライブラリ。 一度確保されたリソースは明示的に解放処理が行われない限りメモリリークが発生してしまうけれどもBoehm GCで用意されている関数群（通常はGC_MALLOC）を使ってリソースを確保すれば不要になった段階で自動的に解放してくれる。 ソースコード全体で統一してこのライブラリを利用していればオブジェクトの寿命管理の手間は減るだろうし自分がコードの責任者であるならば難しいところを枯れたライブラリにお任せできるので安心感はあるのだろう。ちなみにこのライブラリ、以前からその存在は知ってはいたけれどスマートポインタ派の自分としてはオブジェクトの寿命管理のためにこれを使うモチベーションはいまいち感じられない。</p>
<p>そんなBoehm GCは「<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html">Using the Garbage Collector as Leak Detector</a>」で紹介されているようにメモリリーク検知用ユーティリティとしても使える。ドキュメントやソースコードを覗いてみて少し工夫すれば手軽に既存のコードに殆ど手を加えること無くメモリリークの検知ができそうだったので試しにサンプルコードを書いてみた。以下、Boehm GCのインストールからC/C++コードでのメモリリーク検知について。</p>
<h2><strong>Boehm GCインストール</strong></h2>
<p>まずは自分の環境(debina5.0.1&#8243;lenny&#8221;)にBoehm GCをインストールしてみる。 Boehm GCライブラリをつかって開発するには<a href="http://packages.debian.org/lenny/libgc-dev">libgc-dev</a>と<a href="http://packages.debian.org/lenny/libgc1c2">libgc1c2</a>が必要。もし自分の環境に合うパッケージが存在しない場合は直接<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/">ここ</a>から tar.gzボールをダウンロードして例のconfigure、make、make install。</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ sudo apt-get install libgc-dev<br />
$ sudo apt-get install libgc1c2<br />
$ dpkg --list |grep libgc<br />
ii &nbsp;libgc-dev &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1:6.8-1.1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;conservative garbage collector for C (develo<br />
ii &nbsp;libgc1c2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1:6.8-1.1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;conservative garbage collector for C and C++</div></div>
<p><h2><strong>Cコードメモリリーク検知 &#8211; *alloc/freeをGC_関数に置換</strong></h2>
<p>Boehm GCにはGC_MALLOC等のリソース確保系関数でリソース確保されたにもかかわらずGC_FREE等の解放系関数でリソース解放されずにリークしてしまっているオブジェクトを検知してそれらをレポートする機能がある。 このメモリリーク検知レポートはGC_gcollect関数で実行される。ただしこのときメモリリーク検知レポート機能をオンにするためにはそもそもBoehm GC を-DFIND_LEAKオプションでコンパイルするか、または実行時にダイナミックにGC_find_leak=1をセットしてやる必要がある。</p>
<ul>
<li>対象オブジェクト: GC_MALLOC等でリソース確保されたにもかかわらずGC_FREE等で解放されないオブジェクト</li>
<li>検知レポート実行関数： GC_gcollect</li>
<li>前提条件： -DFIND_LEAKオプションでコンパイルされたBoehmGC or 実行時にGC_find_leak=1をセット</li>
</ul>
<p>
「<a href="http：//www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html">Using the Garbage Collector as Leak Detector</a>」ではこのメモリリーク検知レポート機能を利用して実際のCコードのメモリリークを検知するために直接ヒープからメモリ確保、解放を行うための基本関数をBoehmGCの関数で置き換えるためのヘッダを用意している。</p>
<p><span style="text-decoration: underline;">gc_detect_leaks.h</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#define GC_DEBUG</span><br />
<span style="color: #339933;">#include &quot;gc.h&quot;</span><br />
<span style="color: #339933;">#define malloc(n) GC_MALLOC(n)</span><br />
<span style="color: #339933;">#define calloc(m,n) GC_MALLOC((m)*(n))</span><br />
<span style="color: #339933;">#define free(p) GC_FREE(p)</span><br />
<span style="color: #339933;">#define realloc(p,n) GC_REALLOC((p),(n))</span><br />
<span style="color: #339933;">#define CHECK_LEAKS() GC_gcollect()</span></div></div>
<p>試しにメモリリークを引き起こすコードに上記ヘッダをインクルードしたサンプルコード(t1.c)を用意してコンパイル+ 実行してみる。<br />
<span style="text-decoration: underline;">サンプルコード: t1.c</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;stdio.h&gt;</span><br />
<span style="color: #339933;">#include &quot;gc_detect_leaks.h&quot;</span><br />
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; GC_find_leak <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>a<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; a <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/malloc.html"><span style="color: #000066;">malloc</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>　　<span style="color: #666666; font-style: italic;">// t1.c: line7</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//free(a);</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CHECK_LEAKS<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[コンパイルと実行結果]<br />
$ gcc -g -Wall t1.c -o t1 -I/usr/include/gc -L/usr/lib -lgc<br />
$ ./t1<br />
Leaked composite object at 0x805af90 (t1.c:7, sz=100, NORMAL)<br />
Leaked composite object at 0x805af10 (t1.c:7, sz=100, NORMAL)<br />
Leaked composite object at 0x805af90 (t1.c:7, sz=100, NORMAL)<br />
...</div></div>
<p>無事メモリリークを検知。メモリリークの原因となっている箇所（t1.cの７行目）も特定されているので合格。ちなみに上記ヘッダでGC_DEBUGをdefineしているは理由は<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gch.txt">gc.h</a>で定義されているGC_MALLOCをデバック用出力にモードにするため。以下gc.hの該当部分だけを略して抜粋。</p>
<p><span style="text-decoration: underline;">gc6.8 &#8211; /usr/local/gc/gc.h</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#ifdef GC_ADD_CALLER</span><br />
<span style="color: #339933;"># &nbsp;define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__</span><br />
...略...<br />
<span style="color: #339933;">#else</span><br />
<span style="color: #339933;"># &nbsp;define GC_EXTRAS __FILE__, __LINE__</span><br />
...略...<br />
<span style="color: #339933;">#endif</span><br />
<br />
<span style="color: #339933;"># ifdef GC_DEBUG</span><br />
<span style="color: #339933;"># &nbsp; define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)</span><br />
... 略...<br />
<span style="color: #339933;"># else</span><br />
<span style="color: #339933;"># &nbsp; define GC_MALLOC(sz) GC_malloc(sz)</span><br />
...略...<br />
<span style="color: #339933;"># endif</span></div></div>
<p><h2><strong>C++ コードメモリリーク検知 &#8211; gc/gc_cleanupクラスで継承</strong></h2>
<p>次にC++コードのメモリリーク検知を行う。C++のデータ構造の基本はクラス（細かいことを省けば構造体もクラス）でありクラスはnewオペレーターでメモリを動的に確保する。 当然のことながらデフォルトのnewオペレータでリソース確保した場合はGC回収不能であるためBoehm GCが用意しているC++用ライブラリを利用する。<a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc_cpph.txt">gc_cpp.h</a>をみるとこれは単なるCライブラリのラップクラス。以下のようにgcやgc_cleanupクラスをベースクラスとすることでGC回収可能なオブジェクトとして扱うことができる。</p>
<p><span style="text-decoration: underline;">サンプルコード: t2.cpp</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;stdio.h&gt;</span><br />
<span style="color: #339933;">#define GC_DEBUG</span><br />
<span style="color: #339933;">#include &quot;gc_cpp.h&quot;</span><br />
<span style="color: #339933;">#define CHECK_LEAKS() GC_gcollect()</span><br />
class Foo<span style="color: #339933;">:</span> public gc<span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; GC_find_leak <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Foo <span style="color: #339933;">*</span>f<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f <span style="color: #339933;">=</span>new Foo<span style="color: #339933;">;</span>　　　<span style="color: #666666; font-style: italic;">// t2.cpp: line10</span><br />
<span style="color: #666666; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp;delete f;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CHECK_LEAKS<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[コンパイルと実行結果]<br />
$ g++ -g -Wall t2.cpp -o t2 -I/usr/include/gc -L/usr/lib -lgc<br />
$ ./t2<br />
Leaked composite object at 0x805afe8 (/usr/include/gc/gc_cpp.h:274, sz=1, NORMAL)<br />
Leaked composite object at 0x805afd0 (/usr/include/gc/gc_cpp.h:274, sz=1, NORMAL)<br />
Leaked composite object at 0x805afe8 (/usr/include/gc/gc_cpp.h:274, sz=1, NORMAL)<br />
....</div></div>
<p>これも無事メモリリーク検知はされている。ただしリーク箇所が/usr/include/gc/gc_cpp.hのL274行目を指している。これではリークの原因箇所がわからない。できればt2.cppのL10行目(f=new Foo)を指してもらいたい。さらにこの方法では単に既存のコードのメモリーリーク検知のみを行いたい場合でも、クラスをgc やgc_cleanupクラスで継承させるといったコードに手を加えていく作業が必要があるのでとても面倒でありコード量が多ければ多いほど手間がかかる。</p>
<p><h2><strong>C++コードメモリリーク検知 &#8211; new/deleteオペレータのオーバーロード</strong></h2>
<p>そこで既存のコードにあまり手を加えなくてもメモリリーク検知ができ、且つリークの原因箇所を特定できる方法を考えてみた。まずは既存のコードの手を加えないでメモリリーク検知する方法。クラスはリソースの確保、解放をそれぞれnew、 deleteオペレータで行うのでこれらをグローバルにオーバーロードしてやり内部のリソース確保、解放のための実装をGC関数で置き換えてやる。そしてそのヘッダを既存のコードにインクルードしてやれば既存のコードに手を加えないでメモリーリークの検知ができるのではないかと。 ヘッダは以下のような感じ。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#define GC_DEBUG</span><br />
<span style="color: #339933;">#include &quot;gc.h&quot;</span><br />
<span style="color: #993333;">void</span><span style="color: #339933;">*</span> operator new<span style="color: #009900;">&#40;</span><span style="color: #993333;">size_t</span> size<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> GC_MALLOC<span style="color: #009900;">&#40;</span>size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span><span style="color: #339933;">*</span> operator new<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">size_t</span> size<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> GC_MALLOC<span style="color: #009900;">&#40;</span>size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span> operator delete<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span> p<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span> GC_FREE<span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span> &nbsp;operator delete<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span> p<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span> GC_FREE<span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>ただしこれだけではメモリリークの検知はできてもリークの原因箇所の特定が難しい。このままだと上記ヘッダのGC_MALLOC()コール箇所がリーク箇所としてレポートされてしまう。 理想はnewオペレータをコールしている箇所がレポートされて欲しい。ということで次のように GC_debug_malloc()にnewオペレータコール箇所のファイル名と行を渡すように変更してみる。</p>
<p><span style="text-decoration: underline;">gc_detect_leaks.h</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#define GC_DEBUG</span><br />
<span style="color: #339933;">#include &quot;gc.h&quot;</span><br />
<span style="color: #993333;">void</span><span style="color: #339933;">*</span> operator new<span style="color: #009900;">&#40;</span><span style="color: #993333;">size_t</span> size<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> s<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> GC_debug_malloc<span style="color: #009900;">&#40;</span>size<span style="color: #339933;">,</span>s<span style="color: #339933;">,</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span><span style="color: #339933;">*</span> operator new<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">size_t</span> size<span style="color: #339933;">,</span> &nbsp;<span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> s<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> GC_debug_malloc<span style="color: #009900;">&#40;</span>size<span style="color: #339933;">,</span>s<span style="color: #339933;">,</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span> operator delete<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span> p<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span> GC_debug_free<span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span> &nbsp;operator delete<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span> p<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span> GC_debug_free<span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #339933;"># &nbsp; define new new(__FILE__, __LINE__)</span><br />
<span style="color: #339933;"># &nbsp; define CHECK_LEAKS() GC_gcollect()</span><br />
<span style="color: #993333;">int</span> GC_find_leak <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span></div></div>
<p>ためしにメモリリークを引き起こすC++コードに上記ヘッダをインクルードしたものを用意してコンパイル+ 実行してみる。今度はヘッダにint GC_find_leak = 1を含めているのでサンプルコードにGC_find_leak = 1をセットする必要はない。</p>
<p><span style="text-decoration: underline;">サンプルコード: t3.cpp</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;stdio.h&gt;</span><br />
<span style="color: #339933;">#include &quot;gc_detect_leaks.h&quot;</span><br />
class Foo<span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; Foo <span style="color: #339933;">*</span>f<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; f <span style="color: #339933;">=</span>new Foo<span style="color: #339933;">;</span> &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// t3.cpp: line7</span><br />
<span style="color: #666666; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp;delete f;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CHECK_LEAKS<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[コンパイルと実行結果]<br />
$ g++ -g -Wall t3.cpp -o t3 -I/usr/include/gc -L/usr/lib -lgc<br />
$ ./t3<br />
Leaked composite object at 0x805afe8 (t3.cpp:7, sz=1, NORMAL)<br />
Leaked composite object at 0x805afd0 (t3.cpp:7, sz=1, NORMAL)<br />
Leaked composite object at 0x805afe8 (t3.cpp:7, sz=1, NORMAL)<br />
...</div></div>
<p>見事メモリリークを検知しnewオペレータをコールしている行がレポートされた。というわけでこのヘッダをインクルードするだけで他の既存のコードに手を加えることなくメモリリークを検知することができた。</p>
<p>最後に、今回使ったサンプルコードとここで紹介したヘッダを少し体裁を整えて<a href="http://github.com/yokawasa/any/tree/master/boehmgc/">github</a>にあげておきました。ちなみにgithubにあげたgc_detect_leaks.hを使う際は-DGC_DETECT_MEM_LEAKでコンパイルすることをお忘れなく。</p>
<p><a href="http://github.com/yokawasa/any/tree/master/boehmgc/">http://github.com/yokawasa/any/tree/master/boehmgc/</a></p>
<p>おわり</p>
<iframe src="http://www.facebook.com/plugins/like.php?href=http://yk55.com/blog/2010/03/25/boehm_gc_detect_memory_leak/&amp;layout=button_count&amp;show_faces=1&amp;width=450&amp;action=like&amp;colorscheme=light&amp;font=arial" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:25px"></iframe>]]></content:encoded>
			<wfw:commentRss>http://yk55.com/blog/2010/03/25/boehm_gc_detect_memory_leak/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	<!-- google_ad_section_end --></channel>
</rss>

