Seg Fault When Reading File w/ Class Obj. - STL Problem?

Hello All,

I am attempting to write an N-dimensional histogram class for a project I am working on using v4.00.04 on Fedora 1. I decided to implement this by having a member map<string,TAxis*> in the class as well as a index map<string,int>. Everything compiles and links fine, but when I try to read the multidimensional histogram object back from a ROOT file, I get a segfault.

I have attached a tarball containing the class header, source, linkdef, a short test script, and a Makefile. The backtrace I get from the segfault is below. Does anyone know what I’m doing wrong? I have a feeling the map streamer is not being handled correctly, although I’m not sure.

#0  chunk_free (ar_ptr=0x41922c80, p=0x897db1c) at malloc.c:3180
#1  0x41870fc0 in __libc_free (mem=0x897db24) at malloc.c:3154
#2  0x4056fd25 in operator delete (ptr=0x3000000)
    at ../../../../../gcc-3.1/libstdc++-v3/libsupc++/del_op.cc:39
#3  0x401841b7 in TStorage::ObjectDealloc ()
   from /d0usr/products/root/Linux-2-4/v4_00_04a_rh71_locked-GCC_3_1--opt/lib/libCore.so
#4  0x40169cb1 in TObject::operator delete ()
   from /d0usr/products/root/Linux-2-4/v4_00_04a_rh71_locked-GCC_3_1--opt/lib/libCore.so
#5  0x40a9af04 in TH1F::~TH1F ()
   from /d0usr/products/root/Linux-2-4/v4_00_04a_rh71_locked-GCC_3_1--opt/lib/libHist.so
#6  0x401bdbe9 in TObjectTable::Delete ()
   from /d0usr/products/root/Linux-2-4/v4_00_04a_rh71_locked-GCC_3_1--opt/lib/libCore.so
#7  0x401b385d in TCollection::EmptyGarbageCollection ()
   from /d0usr/products/root/Linux-2-4/v4_00_04a_rh71_locked-GCC_3_1--opt/lib/libCore.so
#8  0x40152992 in TFile::Close ()
   from /d0usr/products/root/Linux-2-4/v4_00_04a_rh71_locked-GCC_3_1--opt/lib/libCore.so
#9  0x0804e216 in main () at testing.cpp:62

Thanks in advance,
Dan
mDimHist.tar.gz (2.87 KB)

Hi,

The likely cause is

class mDimHist: public TObject{ public: .... private: TH1F _hglobal; //global 1d histogram
plus the fact that you did not add something lke

Hence the directory is still added to the current TFile and is deleted by this TFile (hence it is double deleted)

Cheers,
Philippe.

Hi,
Thanks for the quick reply. I added _hglobal.SetDirectory(0) to each of the constructors, but the test program still crashes. I then tried to do

mDimHist mdh; mdh.GetHGlobal()->SetDirectory(0);
but that crashes with a different seg fault.

I also print out the directory after I read back the object from the file.

TFile *fin=new TFile("testing.root","READ"); mDimHist *mdh=(mDimHist *)fin->Get("mdh"); mdh->GetHGlobal()->GetDirectory()->Print();
and this shows that the directory of _hglobal is not 0 even though I set it that way in the constructor.

Clearly, I am confused about the right way to do this. Any help would be appreciated.

Thanks,
Dan

In order for the change to work in both the writing and reading situation, you have to put the _hglobal.SetDirectory(0); in each of the constructors and in the Streamer.
You could also just use:

TH1::AddDirectory(false); Also to have a complete dictionary you should add #pragma link C++ class pair<string,TAxis*>+; to your linkdef file.

Cheers,
Philippe.

Hi,

Thanks for all the help. I turned off streamer generation in the linkdef #pragma link C++ class mDimHist-; and added a custom streamer to the class:

[code]void mDimHist::Streamer(TBuffer &R__b)
{
// Stream an object of class mDimHist.

if (R__b.IsReading()) {
mDimHist::Class()->ReadBuffer(R__b, this);
_hglobal.SetDirectory(0);
}
else {
mDimHist::Class()->WriteBuffer(R__b, this);
_hglobal.SetDirectory(0);
}

}[/code]

My test program still seg faults, although now it traces back to:

#0 main () at /d0usr/products/root/Linux-2-4/v4_00_04a_rh71_locked-GCC_3_1--opt/include/TH1.h:49 49 #endif

Looking up that block in TH1.h,

#ifndef ROOT_TArrayS #include "TArrayS.h" #endif

I’m afraid I still don’t understand what’s happening.

Thanks again,
Dan

Hi,

I can not reproduce this problem.
I suspect a build issue (i.e. it would go away if you rebuild from scratch).
If this does not solve the issue I recommend that you
[ul]compile in full debug mode (add -g and remove all -O from the gcc command line)
use valgrind (valgrind.kde.org)
[/ul]
Cheers,
Philippe.

Hi,

I found the source of the problem. I had stupidly modified the test script to print out a non-existent directory.

mDimHist *mdh=(mDimHist *)fin->Get("mdh"); mdh->GetHGlobal()->GetDirectory()->Print();

This, of course, is a seg fault since mdh->GetHGlobal->GetDirectory=0. I don’t understand why the backtrace is so strange; I guess any kind of behavior is possible when you try to use a NULL pointer.

Thank you so much for taking the time to help me. I really appreciate it.

Dan