CINT bug

From: Tom Roberts <tjrob_at_fnal.gov>
Date: Thu, 24 Apr 2008 14:47:45 -0500


I have (finally!) figured out why my big Root macro is crashing. It is due to a bug in CINT that causes it to get confused between the following functions:

	Plot::Plot(TNtuple *_nt, const char *x)
	Plot::Plot(TNtuple *_nt[], const char *x)

The attached test8.C illustrates the problem. g4beamline.root is a small file it opens.

The really crazy thing is that this test program crashes on Root 5.16, while the full macro works. Both crash on 5.18 (which is what I'm trying to fix).

Clearly CINT is using the wrong constructor when called with a non-array pointer and for some reason that invalid call does not crash, but the valid call with an array does crash:

root [0] .X test8.C
Ntuple 'VirtualDetector/Det1' opened
TTreeFormula created
array constructor entered
Just before crash
Just after crash
array constructor entered
Just before crash

Re-writing "TNtuple *_nt[]" as "TNtuple **_nt" changes where it crashes, still calling the wrong constructor. BIG CLUE: Root 5.16 with the original test8.C behaves as does 5.18 with this modified macro.

All this suggests a workaround: avoid passing a pointer array as an argument to the constructor.

Another unexpected surprise: try commenting out the #include and run it again -- I get 8 errors on line 9, which ostensibly does not use any TG functions at all!

Tom Roberts

// test8.C

#include <TGClient.h> // force Root to load libGui.

class Plot {

	TNtuple **ntuples;
	int nNtuples;
	const char *expr_x;
	TTreeFormula *xf;
public:
	/// Constructor.
	Plot(TNtuple *_nt[], const char *x);
	Plot(TNtuple *_nt, const char *x);

};

Plot::Plot(TNtuple *_nt[], const char *x)
{

printf("array constructor entered\n");

	expr_x = StrDup(x);
	if(expr_x && *expr_x=='\0') expr_x=0;

	xf = 0;

	// use the first selected NTuple for expressions
	TNtuple *nt = _nt[0];

	if(expr_x) {
printf("Just before crash\n"); fflush(stdout);
		xf = new TTreeFormula("x",expr_x,nt);
printf("Just after crash\n"); fflush(stdout);
		if(xf->GetTree() == 0) { delete xf; xf = 0; }
	}

}

Plot::Plot(TNtuple *_nt, const char *x)
{

printf("non-array constructor entered\n");

	expr_x = StrDup(x);
	if(expr_x && *expr_x=='\0') expr_x=0;

	xf = 0;

	// use the first selected NTuple for expressions
	TNtuple *nt = _nt;

	if(expr_x) {
		xf = new TTreeFormula("x",expr_x,nt);
		if(xf->GetTree() == 0) { delete xf; xf = 0; }
	}
	printf("non-array constructor returns\n");
}

// here is the macro function (CINT default optimization level 4 screws up) void test8()
{

	gROOT->ProcessLine(".O 3");
	char *filename = "g4beamline.root";
	char *ntuplename = "VirtualDetector/Det1";
	TFile *file = new TFile(filename,"READ");
	if(file->IsZombie()) {
		printf("Cannot read '%s'\n",filename);
		file = 0;
		return;
	}
	TNtuple *ntuple = dynamic_cast<TNtuple*>(file->Get(ntuplename));
	if(!ntuple) {
		printf("Cannot find NTuple '%s'\n",ntuplename);
		return;
	}
	printf("Ntuple '%s' opened\n",ntuplename);

	TTreeFormula *xf = new TTreeFormula("test","x",ntuple);
	printf("TTreeFormula created\n");

	new Plot(ntuple,"x");

	int n=1;
	TNtuple **array = new TNtuple*[n];
	array[0] = ntuple;

	new Plot(array,"x");

}
Received on Thu Apr 24 2008 - 21:48:18 CEST

This archive was generated by hypermail 2.2.0 : Fri Apr 25 2008 - 11:50:01 CEST