Examine the stack

Hi,

I have the error below in a program, which uses the ROOT libraries and I can’t find the solution. It seems to be in the destructor of a TH1F object.

The error occurs when a scope is left (from a for loop), so I assume that it has to do with a variable on the stack.

I would like to get the list of TH1F objects on the stack, so I looked for something like gROOT->GetListOfLocals(), but such a thing is not there (or is there?).

Any hints on how to proceed and maybe anyone sees where my problem could be by looking at the backtrace of my program’s crash below?:

Many thanks,

Ytsen.

*** Break *** segmentation violation
Using host libthread_db library “/lib/tls/libthread_db.so.1”.
Attaching to program: /proc/27398/exe, process 27398
[Thread debugging using libthread_db enabled]
[New Thread -1208326464 (LWP 27398)]
0x004127a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x026ddff3 in __waitpid_nocancel () from /lib/tls/libc.so.6
#2 0x02688469 in do_system () from /lib/tls/libc.so.6
#3 0x0016f84d in system () from /lib/tls/libpthread.so.0
#4 0x01128883 in TUnixSystem::Exec ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#5 0x0112df65 in TUnixSystem::StackTrace ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#6 0x0112ac5d in TUnixSystem::DispatchSignals ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#7 0x0112ad64 in SigHandler ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#8 0x01129f55 in sighandler ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#9
#10 0x004d288e in TH1::~TH1$base ()
from /opt/products/root/5.17.03ah/lib/libHist.so.5.17
#11 0x004e9a6a in TH1F::~TH1F ()
from /opt/products/root/5.17.03ah/lib/libHist.so.5.17
#12 0x08065b88 in main (argc=2, argv=0xbff2b3e4)
at /usr/lib/gcc/i386-redhat-linux/3.4.6/…/…/…/…/include/c++/3.4.6/ext/new_allocator.h:69
[h1desy10] /user/ytsen/h1/oo31/MarPlotXsec $

Program and libs:

[h1desy10] /user/ytsen/h1/oo31/MarPlotXsec $ ldd which DrawXsec
libTMarHisto.so => …/lib/i586_rhel40/libTMarHisto.so (0x00520000)
libH1Steering.so => /afs/desy.de/group/h1/root/checkout/oo-releases/releases/3.1.15/lib/i586_rhel40/libH1Steering.so (0x00a92000)
libH1Arrays.so => /afs/desy.de/group/h1/root/checkout/oo-releases/releases/3.1.15/lib/i586_rhel40/libH1Arrays.so (0x0073a000)
libCore.so.5.17 => /opt/products/root/5.17.03ah/lib/libCore.so.5.17 (0x00adf000)
libCint.so.5.17 => /opt/products/root/5.17.03ah/lib/libCint.so.5.17 (0x02631000)
libRIO.so.5.17 => /opt/products/root/5.17.03ah/lib/libRIO.so.5.17 (0x00111000)
libNet.so.5.17 => /opt/products/root/5.17.03ah/lib/libNet.so.5.17 (0x00215000)
libHist.so.5.17 => /opt/products/root/5.17.03ah/lib/libHist.so.5.17 (0x00776000)
libGraf.so.5.17 => /opt/products/root/5.17.03ah/lib/libGraf.so.5.17 (0x042c6000)
libGraf3d.so.5.17 => /opt/products/root/5.17.03ah/lib/libGraf3d.so.5.17 (0x00305000)
libGpad.so.5.17 => /opt/products/root/5.17.03ah/lib/libGpad.so.5.17 (0x00429000)
libTree.so.5.17 => /opt/products/root/5.17.03ah/lib/libTree.so.5.17 (0x0058d000)
libRint.so.5.17 => /opt/products/root/5.17.03ah/lib/libRint.so.5.17 (0x003e4000)
libPostscript.so.5.17 => /opt/products/root/5.17.03ah/lib/libPostscript.so.5.17 (0x004d8000)
libMatrix.so.5.17 => /opt/products/root/5.17.03ah/lib/libMatrix.so.5.17 (0x06dce000)
libPhysics.so.5.17 => /opt/products/root/5.17.03ah/lib/libPhysics.so.5.17 (0x009d6000)
libdl.so.2 => /lib/libdl.so.2 (0x0057d000)
libTreePlayer.so.5.17 => /opt/products/root/5.17.03ah/lib/libTreePlayer.so.5.17 (0x063ef000)
libEG.so.5.17 => /opt/products/root/5.17.03ah/lib/libEG.so.5.17 (0x0471b000)
libg2c.so.0 => /usr/lib/libg2c.so.0 (0x00529000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x010f5000)
libm.so.6 => /lib/tls/libm.so.6 (0x00558000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00546000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x00706000)
libc.so.6 => /lib/tls/libc.so.6 (0x011c0000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x07444000)
/lib/ld-linux.so.2 (0x00412000)

You’d better give us your program or at least some excerpt.

Thanks for the answer about the error. I have no “minimal version showing the problem” unfortunately.

But does ROOT provide tools to examine the stack to get a hint about which object ROOT is trying to delete illegally?

Many thanks,

Ytsen.

[quote]Thanks for the answer about the error. I have no “minimal version showing the problem” unfortunately.

But does ROOT provide tools to examine the stack to get a hint about which object ROOT is trying to delete illegally?

Many thanks,

Ytsen.[/quote]

IMHO Your original question is very similar to “oh, my program crashes! what’s wrong?” So the aswer is “O!!! Something must be wrong!”.

One way to debug your program is to use gdb, another - valgrind.
The simplest way is to localize your error and obtain minimal program reproducing problem (comment/uncomment critical part of code to identify the place).

You think, the reason is stack. But it’s a guess work, show program fragment. And your stack trace is not very usefull (at least for me)

Okay, found the problem in the mean time by eliminating code.

This was the responsible code:

TH1F hData;

if (fData->IsOpen() ) {

hData = * (TH1F *) ( fData.Get( (*hNameIt).c_str()) )->Clone(); // copy

};

When going out of this scope, the mentioned error occurs. Apparantly the copy-constructor is not invoked by the “*” in the definition?

If someone knows how to get thelist of histograms on the stack, or how to examine the stack at run time, I am still very much interested (using ROOT tools that is).

Many thanks,

Ytsen.

Do you really understand what you’re doing in your code?

TH1F hData; //stack object

hData = /////assignment copy operator

fData.Get( (*hNameIt).c_str())

what is fData? TFile?

You obtain some object from file, ok (you actually have a pointer)

(fData.Get(name))->Clone() you call clone, ok, let’s assume dynamic type of object from file is TH1F.

(TH1F *)ptrToTobj you casted your pointer

*(TH1F *)ptrToObj you dereference your pointer (got TH1F &)
and now assign. First of all, do you understand, that you have memory leak here?

Yes I do.

Actually the Clone() was not there (bad copy-paste, sorry).

hData is on the stack where I want it. In the scope of the if-statement I want to construct a copy of the object in the file:

hData = * (TH1F *) ( fData.Get( (*hNameIt).c_str()) );

And I do not understand why it goes wrong when the scope of the if-statement is left.

Why don’t you explain why the crash is normal and tell me what I should do?

Thanks,

Ytsen.

PS. It doesn’t crash using gcc version 3.3.3 and root 5.12.00a(h) and same code.

PPS. I am still interested in how to get the list of histograms :slight_smile:

[quote]Okay, found the problem in the mean time by eliminating code.

This was the responsible code:
[/quote]

BTW your code excerpt though contains serious problems does not reproduce your problem.

  1. hData = expr that’s not a copy construction. This is assignment.
  2. This code sample does not reproduce crash. Do you compile it?
    Or do you interpret your macro with CINT?

Lifetime of your hData is not the if-scope, it’s enclosing scope.
So, why are you interested in stack, if you do not really understand what is stack ? :wink:

Look man, I am a physicist and you are probably an IT expert. Every nested scope is a stack-frame to me and when you go out of scope, all that is on the stack is deleted when not by hand allocated with “new”.

I had a whole bunch of stuff on the stack and was wondering which one of them was causing the trouble, so I was looking for a ROOT tool that could give me that info. Is there such a thing?

You say that the “*” operator does not invoke the copy constructor and the “=” is an assignment. Ownership conflict I conclude in destroying the stack’s objects, why no warning during compilation?

The problem was gone when I made hData a pointer and let it point to a clone of the TH1F from the file. Therefore I concluded that my construction using the “*” must’ve been the cause of my trouble.

Cheers,

Ytsen.

What is “it” and “same code”? 1. Your full program? 2. Or sample code?
If 1. - so, what’s your problem?
If 2. - you gave wrong sample code and your problem is somewhere else.

It’s 1), I didn’t make a sample code to study this problem (yet).

[quote]Look man, I am a physicist and you are probably an IT expert.
[/quote]
Doesn’t matter, who I am, I want to help you, but you strongly resist, I do not know, why :slight_smile:

//block scope
A a;//lifetime of a started here.
if(condition)
{
//nested block
   a = something;//assignment, not copy construction.
///
}//a's lifetime does not end here

///
a.Some();//a's still alive.
//

First, you have to understand where is you real problem.
For example, you call some function, and your program crashes.
Show us this function definition. I guess, there is no top-secret code there.

Compiler cannot check logic of your program, only syntax and some semantics. There is not semantic or syntax problems in your program, so, how compiler can find anything?

*ptr is dereferencing, it simply produces l-value of some type (Ok, you can overload this operator for your class, but that’s not your case :slight_smile: ):

int i = 10;
int * p = &i;
*p; this expression is an l-value of type int and it refers to i.

One more time. Your program sample does not crash.

I apologize that my sample program was flawed, I didn’t want to draw everybody into my code, I just wanted a tool to examine the stack.

Anyway, here is a proper sample code that shows (my) problem, maybe I still don’t understand it.

#include <iostream.h>
#include <stdlib.h>

// ROOT includes
#include <TFile.h>
#include <TROOT.h>
#include <TH1.h>

int main(int argc, char* argv[]) {

{

TH1F hData;

TFile f("../MarIsolTau/histo.0607.W_Epvec.VT41.elmu.root","READ");

if (f.IsOpen()) {
  hData = * (TH1F*) f.Get("hElecTh");
};

hData.Print();

cout << "Going out of scope and crash now... " << endl;

};

cout << “Done” << endl;
return 0;
};

[h1paroia] /user/ytsen/h1/oo31/H1Examples $ test.th1.destruction.shit
TH1.Print Name = hElecTh, Entries= 317, Total sum= 254.316
Going out of scope and crash now…

*** Break *** segmentation violation
Using host libthread_db library “/lib/tls/libthread_db.so.1”.
Attaching to program: /proc/12982/exe, process 12982
[Thread debugging using libthread_db enabled]
[New Thread -1208391456 (LWP 12982)]
0x00af07a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x054f5ff3 in __waitpid_nocancel () from /lib/tls/libc.so.6
#2 0x054a0469 in do_system () from /lib/tls/libc.so.6
#3 0x00d6f84d in system () from /lib/tls/libpthread.so.0
#4 0x01178883 in TUnixSystem::Exec ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#5 0x0117df65 in TUnixSystem::StackTrace ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#6 0x0117ac5d in TUnixSystem::DispatchSignals ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#7 0x0117ad64 in SigHandler ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#8 0x01179f55 in sighandler ()
from /opt/products/root/5.17.03ah/lib/libCore.so.5.17
#9
#10 0x06cf688e in TH1::~TH1$base ()
from /opt/products/root/5.17.03ah/lib/libHist.so.5.17
#11 0x06d0da6a in TH1F::~TH1F ()
from /opt/products/root/5.17.03ah/lib/libHist.so.5.17
#12 0x08048eb0 in main (argc=1, argv=0xbff29524)
at /usr/lib/gcc/i386-redhat-linux/3.4.6/…/…/…/…/include/c++/3.4.6/bits/ostream.tcc:63

And this does not work either (giving the clone a new name):

hData = (TH1F*) f.Get(“hElecTh”)->Clone(“nieuw”);

Then the print statement already leads to a crash …

Well, I slightly modified your program, I do not have your file. BTW, attach it! I promise to use it only for debug :slight_smile:

#include <iostream>

// ROOT includes
#include <TFile.h>
#include <TROOT.h>
#include <TH1.h>


void create()
{
   TFile f("laja.root", "RECREATE");
   f.cd();
   TH1F hist("hist", "hist", 10, -1., 1.);
   hist.FillRandom("gaus");
   hist.Write();
   f.Close();
}


void laja()
{
   create();

   {
      TH1F hData;
      TFile f("laja.root", "READ");
      if (f.IsOpen()) {
         hData = * (TH1F*) f.Get("hist");
      }

      hData.Print();

      std::cout << "Going out of scope and crash now... " << std::endl;
   }

   std::cout << "Done" << std::endl;
}

If I do in ROOT:

.L laja.C+

and
laja()

I have an output:

With cvs head of ROOT on windows.

Here is the file.
test.th1.destruction.shit.C (784 Bytes)

Really stupid problem, I see now. May be, that’s something WRONG with object ownership and blah-blah-blah.

And please, return to non-pointer version (take, for example, mine).
If after if(){} block I add hData.SetDirectory(0); program will not crash, at least for me.

#include <iostream>

#include <TFile.h>
#include <TH1.h>

void create()
{
   TFile f("laja.root", "RECREATE");
   f.cd();
   TH1F hist("hist", "hist", 10, -1., 1.);
   hist.FillRandom("gaus");
   hist.Write();
}


void laja()
{
   create();

   {
      TH1F hData;
      TFile f("laja.root", "READ");

      if (f.IsOpen()) {
         hData = * (TH1F*) f.Get("hist");
      }

      hData.SetDirectory(0);
      hData.Print();

      std::cout << "Going out of scope and crash now... " << std::endl;
   }

   std::cout << "Done" << std::endl;
}

But if I do:

#include <iostream>

#include <TFile.h>
#include <TH1.h>

void create()
{
   TFile f("laja.root", "RECREATE");
   f.cd();
   TH1F hist("hist", "hist", 10, -1., 1.);
   hist.FillRandom("gaus");
   hist.Write();
}



void laja()
{
   create();

   {
      TH1F hData;
      std::cout<<"Before = "<<hData.GetDirectory()<<std::endl;
      TFile f("laja.root", "READ");

      if (f.IsOpen()) {
         hData = * (TH1F*) f.Get("hist");
      }

      //hData.SetDirectory(0);
      std::cout<<"After = "<<hData.GetDirectory()<<std::endl;
      hData.Print();

      std::cout << "Going out of scope and crash now... " << std::endl;
   }

   std::cout << "Done" << std::endl;
}

So you see, file object (or who?) becomes an owner of my hData and tries to delete it. That’s wrong behavior of ROOT, surely.

Okay, well, the TH1F::SetDirectory(0) works at least.

Thanks for the tip!

Ytsen.