Wrapped TClonesArray problem with ACLIC

I have a problem with TClonesArray which should have a simple solution (I stripped my code down to the bare essentials, but there is more).

I want to embed a TObject in a class “reading” that I define myself and also embed a TClonesArray that I define in a class “readingarray”. Both are defined in the code below, which I compile with ACLIC.

However, in a root session, when I try to do the following, it ends badly:[code]
gSystem->Load(“readings_C.so”)
reading* b=new reading()
readingarray* aa=new readingarray()
aa->AddReading(b)

*** Break *** segmentation violation
Generating stack trace…
0x00002aaaab5d29de in G__interpret_func + 0x143e from /usr/local/root/lib/libCint.so
0x00002aaaab5c6ec8 in G__getfunction + 0x2278 from /usr/local/root/lib/libCint.so
0x00
[/code]

Anyone has an idea what is wrong here? I must say I don’t really understand the logic of TClonesArrays yet. What constructor of the class reading is needed if I want to add elements to the class readingarray? I tried a few as you see.

The classes compiled with ACLIC to produce readings_C.so are:

[code]#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include “TObject.h”
#include “Riostream.h”
#include "TClonesArray.h"
using namespace std;

class reading : public TObject {
// this is a simple wrapper for a reading
private:
Double_t fTime;

public:

reading()
{
//cout<<“building a class reading”<<endl;
fTime=0;
};

reading(reading* r){
fTime=r->GetTime();
}

reading(TObject* r)
{
reading((reading*)r);
}

~reading()
{
cout<<“destroying a class reading”<<endl;
};

void SetTime(Double_t Time){fTime=Time;}
Double_t GetTime() {return fTime;}
ClassDef(reading,1);
};

class readingarray : public TObject {
// this is a simple wrapper for an array of readings

private:

TClonesArray* fArray;
Int_t fNEntries;

public:
readingarray(){
fNEntries=0;
if (!fArray) fArray=new TClonesArray(“reading”);
}

~readingarray()
{
delete fArray;
fArray=0;
}

Int_t GetEntries(){return fArray->GetEntries();}

void AddReading(reading* r){
fArray->SetOwner();
TClonesArray& A=*fArray;
new(A[0]) reading(r->Clone()) ;
}

TClonesArray* GetArray(){return fArray;}
ClassDef(readingarray,1);
};

[/code]

Hi,readingarray(){ fNEntries=0; if (!fArray) fArray=new TClonesArray("reading"); } When the reading array is constructed, the value of its data member is ‘random’. Hence the statement if (!fArray) would usually be false and leave fArray with a random value (hence NOT pointing to a valid TClonesArray, hence leading to a core dump).

Usereadingarray() { fNEntries=0; fArray=new TClonesArray("reading"); }
In the statement:new(A[0]) reading(r->Clone()) ;
you have a memory leak, since you create a ‘reading’ object by cloning it but never delete. Instead you should use"

or better yet:

if (r) { new A[fNEntries] reading(*r); ++fNEntries; };
I recommend that you do not implement:

reading(TObject* r) { reading((reading*)r); } This is misleading to the user of your class. This would core dumps if you mistakenly pass any but a point to a reading

Cheers,
Philippe

Great! :smiley:
Thanks a bunch for the explanations.