Re: writing/reading objects to/form a file

From: Axel Naumann <Axel.Naumann_at_cern.ch>
Date: Sun, 20 Nov 2005 18:12:57 +0100


Hi Chiara,

let's go through your code; there are several problems...

> class AliTOFCalib: public TObject
> {
> public:
> AliTOFCalib() {fPads= new AliTOFCalParam[npad];}

you should not allocate memory in your default constructor (the one that can be called without arguments). Do it some place else, setting fPads=0 in the default constructor. See the Users' Guide p228. Really, for these basic things the Users' Guide is excellent - that's what it's written for, and Ilka puts a lot of work in it, so please make use of it! root.cern.ch, click on "Users' Guide" in the left panel.

> virtual ~AliTOFCalib(){delete[] fPads;}

This is the wrong delete operator. You only have one element in fPads (i.e. it's not a C array, as in Int_t *aCArray; aCArray=new Int_t[10], where you have aCArray pointing to 10 Int_ts, and where you need to use delete[], the array deleting operator). See e.g. http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=31

> void Browse(TBrowser *b)
> {
> char name[10];
> for(Int_t i=0; i<18; ++i) {
> snprintf(name,sizeof(name),"Sector %2.2d\0",i);

name's size of 10 is not enough for that snprintf. You're protecting it using the s_n_printf version, but still... Also, you don't need to add a terminating \0 at the end, as the char array "..." already has one by default. So you should use:
char name[20]; // better a bit more than a bit less :-) snprintf(name,sizeof(name),"Sector %2.2d",i);

> b->Add(new AliTOFCalSector1(&fPads[i*npad/18]),name);

You do know that this "i*npad/18" is a pure integer calculation (if npad is a non-floating point variable)? Meaning there is no rounding here, e.g. for npad==11 you get

i | i*npad/18
0 | 0
1 | 1*11/18=11/18=0
2 | 2*11/18=22/18=1
3 | 3*11/18=33/18=2

etc. See e.g.
http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode112.html

> }
> }
> void PlotPad(Int_t n) {} // *MENU*
> Bool_t IsFolder() const { return kTRUE; }
>
> private:
> // AliTOFCalParam fPads[npad];
> AliTOFCalParam * fPads;
> ClassDef(AliTOFCalib,1)
> };
>
> where AliTOFCalSector1 is a class I have written, similar to this one.
> I write it on a file:
>
> AliTOFCalib *tc = new AliTOFCalib();
> TFile * file = new TFile("prova.root","recreate");
> tc->Write("tc");
> file->Close();

You should actually call "delete file", not just Close. You create a new TFile object when loading the file, so you should delete the old one.

> and then when trying to read it
>
> AliTOFCalib *cal1 = new AliTOFCalib();

Why do you create a new object, before reading it? The reading part will create a new one anyway. So better do:

AliTOFCalib *cal1 = 0;
Again - Users' Guide.

> TFile *file1 = new TFile("prova.root","read");
> file1->GetObject("prova",cal1);
>
> I get:
>
> *** Break *** segmentation violation
> Generating stack trace...
> 0x51310908 in __libc_free + 0x88 from /lib/tls/libc.so.6
> 0x5123b983 in operator delete(void*) + 0x23 from /usr/lib/libstdc++.so.5

This shows that there is a problem with deleting your objects - probably due to the wrong delete[] operator.

> 0x4f592ef3 in TStorage::ObjectDealloc(void*) + 0x59 from
> /exports1/aliprod1/zampolli/zampolliSoft/ROOT/v5-06-00/lib/libCore.so
> etc...
>
> I do not know, perhaps I do not write anything, since when I dump the
> file I get (the underlined line is the suspicious one...):
>
> file1->Dump()
> ==> Dumping object at: 0x09f4f9c8, name=prova.root, class=TFile
>
> fSumBuffer 0 Sum of buffer sizes of objects
> written so far
> fSum2Buffer 0 Sum of squares of buffer sizes
> of objects written so far
> _*fBytesWrite 0 Number of bytes written to
> this file*_

This is only >0 if you _write_ to the file. But you've (now) opened it as readonly, so it should be 0. Use file1->Map() instead, to see what's in the file. Even this is in the Users' Guide :-)

Cheers, Axel. Received on Sun Nov 20 2005 - 18:13:07 MET

This archive was generated by hypermail 2.2.0 : Tue Jan 02 2007 - 14:45:13 MET