ROOTでHistogramをCloneするときの注意

ROOTでHistogramをCloneするときの注意です。それは

Cloneするとポインタアドレスが変わる

です。例えば

root [] TH1D* h0 = new TH1D();
root [] h0
(class TH1D*) 0x1
root [] TH1D* h1 = new TH1D();
root [] h1
(class TH1D*) 0x2
root [] h0 = (TH1D*)h1->Clone();
root [] h0
(class TH1D*) 0x3

と、ポインタアドレスが変わっています(もちろん、アドレスはわかりやすいように書いてあります)。 ソースの中身を見てみると、Clone()関数はTH1のCopy Constructorを呼んでいるため、そうなっているようです。冷静に考えればそうですよね。。。

ちなみに、前のh0のポインタはどこにいってしまったかというと、それは残っております。簡単な実験をします。

root [] TH1D* h0 = new TH1D("h0","h0",10,-0.5,9.5);
root [] TH1D* h1 = new TH1D("h1","h1",10,-0.5,9.5);
root [] h0->Fill(1);
root [] h1->Fill(8);
root [] h0;
(class TH1D*)0x1
root [] h1;
(class TH1D*)0x2
root [] h0 = (TH1D*)h1->Clone();
(class TH1D*)0x3
root [] h0->Draw() // 8のところのBinにCountがあるHistがDrawされる
root [] TH1D* h2 = (TH1D*)0x1 // 昔のh0のアドレスを入れる
root [] h2->Draw() // 1のところのBinにCountがあるHistがDrawされる

Cloneされる前のポインタは生きておりますね。 これつまり、安易にプログラムのコード中でCloneしまくると、ゾンビが大量生産されることになり、いつかメモリリークを起こします。

インタプリタでやっている分には分かるんだけど、コードを書いているときにもちゃんと気をつけなければ、と思うのでした。

Shoichiro Masuoka

CNS, the Univ. of Tokyo. Dcotoral student

関連項目