Problem with compiling class:

I am running ROOT 5.32 on Mac 10.6.8. I have not built ROOT from source, but I downloaded the pre-compiled library from root.cern.ch/drupal/content/prod … ersion-532: it is root_v5.32.00.macosx106-x86_64-gcc-4.2.tar. I am clearly on a 64-bit architecture as when I do

uname -a

I get

Darwin Francesco-Spanos-MacBook-2.local 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun  7 16:32:41 PDT 2011; root:xnu-1504.15.3~1/RELEASE_X86_64 x86_64

I am trying to compile a program that defines a class called Generator (I am attaching it to this message) and I find the problem I report below.

root [6] .L Generator.cxx++
Info in <TUnixSystem::ACLiC>: creating shared library /Users/francescospano/Work/PhysAn/WorkDesk_Phys/StatForHEP/temp/./Generator_cxx.so
Undefined symbols for architecture x86_64:
  "TList::TList(TList const&)", referenced from:
      Generator::getOutput()     in Generator_cxx_ACLiC_dict.o
      G__Generator_cxx_ACLiC_dict_3313_0_14(G__value*, char const*, G__param*, int)in Generator_cxx_ACLiC_dict.o
  "TTree::TTree(TTree const&)", referenced from:
      Generator::getNtup()     in Generator_cxx_ACLiC_dict.o
      G__Generator_cxx_ACLiC_dict_3313_0_15(G__value*, char const*, G__param*, int)in Generator_cxx_ACLiC_dict.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Error in <ACLiC>: Compilation failed!

Is there any obvious problem I have in my code? (Should I re-build ROOT from source?)
Thanks for any help!

Best,
Francesco
Generator.h (2.58 KB)
Generator.cxx (4.74 KB)

Hi,

Neither TList nor TTree can be returned by value and the two method: TList getOutput(); TTree getNtup();are illegal, you will need to return either by reference or by pointer (and make sure that the return value has the proper lifetime).

Cheers,
Philippe

Hi Philippe,
thanks !
I am now defining the methods as

TList& getOutput();
  TTree& getNtup();

and I am defining the functions as

TTree& Generator::getNtup(){return *theNtup; }
TList& Generator::getOutput(){if (theList.GetSize()!=0) return theList;}

This allows me to compile. I will have to check whether the Ntuple object is propefly filled or not.

I have one question though and I ask you to forgive me if the answer is fundamental C++:when I an return TH1D by value there are no complaints. Why are there problems with TTree and TList?
If a TTree and a TList are defined as local variables in a function call, they will disappear at the end of the function so what does it mean to return a reference? Is this a property of ROOT related to object ownership?
(root.cern.ch/download/doc/8ObjectOwnership.pdf)

[quote=“pcanal”]Hi,

Neither TList nor TTree can be returned by value and the two method: TList getOutput(); TTree getNtup();are illegal, you will need to return either by reference or by pointer (and make sure that the return value has the proper lifetime).

Cheers,
Philippe[/quote]
Generator.cxx (5.08 KB)
Generator.h (2.62 KB)

[quote]I have one question though and I ask you to forgive me if the answer is fundamental C++:when I an return TH1D by value there are no complaints. Why are there problems with TTree and TList?[/quote]Because we intentionally did not implement the copy constructor as the semantic in both case is iffy (and the copy constructor are declared private which make the compilation fails … except with ACLiC where the error is delayed until linking). In the case of TList, the issue is ownership of the content (whether it is passed or not). While in the case of the TTree, it is the issue of the ‘data’ that the TTree points to; when ‘copying’ do you mean to only copy the meta-data (the TTree object itself) or also the data (usually a very very expensive operation).
So rather than picking one of the two options (which will surprise 50% of the users :slight_smile:), we require the copying to be done explicitly.

[quote]If a TTree and a TList are defined as local variables in a function call, they will disappear at the end of the function so what does it mean to return a reference? [/quote]In this case (returning a local object as a reference), the program is ill-formed. (This is C++ syntax/grammar nothing particular to ROOT).

In your code, you are not returning a local variable, you are returning the value held by the data member of Generator and thus are valid until the Generator object deletes them (which it seemingly never does, hence inducing a memory leak … )

Cheers,
Philippe.

P.S. Also the TTree is never explicitly associate with a TFile or detach from the current one and thus it might be inadvertently deleted by a TFile that happen to be the current TFile at the time makeNtup is called.
If you really mean to create an in-memory ntuple, you should explicitly call theNtup->SetDirectory(0).
[This part is specific to the Object ownership rule in ROOT]

Hello Philippe,
thanks it is clearer now!

#-o I am now deleting them in the destructor (still incomplete class) :smiley:

Cheers and thanks,
Francesco