Bug Summary

File:programs/Utilities/root_merge/root_merge.cc
Location:line 228, column 4
Description:Called C++ object pointer is null

Annotated Source Code

1/*
2
3 This macro will add histograms from a list of root files and write them
4 to a target root file. The target file is newly created and must not be
5 identical to one of the source files.
6
7 Author: Sven A. Schmidt, sven.schmidt@cern.ch
8 Date: 13.2.2001
9
10 This code is based on the hadd.C example by Rene Brun and Dirk Geppert,
11 which had a problem with directories more than one level deep.
12 (see macro hadd_old.C for this previous implementation).
13
14 The macro from Sven has been enhanced by
15 Anne-Sylvie Nicollerat <Anne-Sylvie.Nicollerat@cern.ch>
16 to automatically add Trees (via a chain of trees).
17
18 To use this macro, modify the file names in function hadd.
19
20 NB: This macro is provided as a tutorial.
21 Use $ROOTSYS/bin/hadd to merge many histogram files
22
23 */
24
25#include <stdlib.h>
26
27#include <string>
28#include <iostream>
29#include <iomanip>
30using namespace std;
31
32#include <TChain.h>
33#include <TFile.h>
34#include <TH1.h>
35#include <TTree.h>
36#include <TKey.h>
37#include <Riostream.h>
38
39TList *FileList;
40TFile *Target;
41
42const char *OUTPUT_FILENAME = "merged.root";
43
44void Usage(void);
45void ParseCommandLineArguments(int narg, char* argv[]);
46void MergeRootfile( TDirectory *target, TList *sourcelist );
47
48//--------------
49// main
50//--------------
51int main(int narg, char* argv[])
52{
53 // create empty list of input files
54 FileList = new TList();
55
56 // Parse command line to fill list
57 ParseCommandLineArguments(narg, argv);
58
59 // Open ROOT file for output
60 Target = new TFile(OUTPUT_FILENAME,"RECREATE","Produced by root_merge");
61 cout<<"Opened ROOT file \""<<OUTPUT_FILENAME<<"\" ..."<<endl;
62
63 // Merge input files into output file
64 MergeRootfile( Target, FileList );
1
Calling 'MergeRootfile'
65
66 // Close output file
67 Target->Write();
68 delete Target;
69 cout<<endl<<"Closed ROOT file: "<<OUTPUT_FILENAME<<endl;
70
71 return 0;
72}
73
74//--------------
75// Usage
76//--------------
77void Usage(void)
78{
79 cout<<endl;
80 cout<<" root_merge [options] infput_file1 input_file2 input_file3 ..."<<endl;
81 cout<<endl;
82 cout<<"options:"<<endl;
83 cout<<" -o filename set output filename (def:"<<OUTPUT_FILENAME<<")"<<endl;
84 cout<<" -h Print this usage statement"<<endl;
85 cout<<endl;
86 cout<<endl;
87
88 exit(0);
89}
90
91//--------------
92// ParseCommandLineArguments
93//--------------
94void ParseCommandLineArguments(int narg, char* argv[])
95{
96 if(narg==1)Usage();
97
98 for(int i=1; i<narg; i++){
99 if(argv[i][0] == '-'){
100 switch(argv[i][1]){
101 case 'o':
102 i++;
103 OUTPUT_FILENAME = argv[i];
104 break;
105 case 'h':
106 Usage();
107 break;
108 default:
109 cout<<"Unknown option \""<<argv[i]<<"\". Aborting."<<endl;
110 exit(-1);
111 }
112 }else{
113 FileList->Add( TFile::Open(argv[i]));
114 }
115 }
116}
117
118#if 0
119void hadd() {
120 // in an interactive ROOT session, edit the file names
121 // Target and FileList, then
122 // root > .L hadd.C
123 // root > hadd()
124
125 Target = TFile::Open( "result.root", "RECREATE" );
126
127 FileList = new TList();
128 FileList->Add( TFile::Open("hsimple1.root") );
129 FileList->Add( TFile::Open("hsimple2.root") );
130
131 MergeRootfile( Target, FileList );
132
133}
134#endif
135
136//--------------
137// MergeRootfile
138//--------------
139void MergeRootfile( TDirectory *target, TList *sourcelist ) {
140
141 // cout << "Target path: " << target->GetPath() << endl;
142 TString path( (char*)strstr( target->GetPath(), ":" ) );
143 path.Remove( 0, 2 );
144
145 TFile *first_source = (TFile*)sourcelist->First();
146 first_source->cd( path );
147 TDirectory *current_sourcedir = gDirectory(TDirectory::CurrentDirectory());
148
149 // loop over all keys in this directory
150 TChain *globChain = 0;
2
'globChain' initialized to a null pointer value
151 TIter nextkey( current_sourcedir->GetListOfKeys() );
152 TKey *key;
153 while ( (key = (TKey*)nextkey())) {
3
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
21
Loop condition is true. Entering loop body
154
155 // read object from first source file
156 first_source->cd( path );
157 TObject *obj = key->ReadObj();
158
159 if ( obj->IsA()->InheritsFrom( "TH1" ) ) {
4
Taking false branch
10
Taking false branch
16
Taking false branch
22
Taking true branch
160 // descendant of TH1 -> merge it
161
162 // cout << "Merging histogram " << obj->GetName() << endl;
163 TH1 *h1 = (TH1*)obj;
164
165 // loop over all source files and add the content of the
166 // correspondant histogram to the one pointed to by "h1"
167 TFile *nextsource = (TFile*)sourcelist->After( first_source );
168 while ( nextsource ) {
23
Loop condition is false. Execution continues on line 223
169
170 // make sure we are at the correct directory level by cd'ing to path
171 nextsource->cd( path );
172 TH1 *h2 = (TH1*)gDirectory(TDirectory::CurrentDirectory())->Get( h1->GetName() );
173 if ( h2 ) {
174 h1->Add( h2 );
175 delete h2; // don't know if this is necessary, i.e. if
176 // h2 is created by the call to gDirectory above.
177 }
178
179 nextsource = (TFile*)sourcelist->After( nextsource );
180 }
181 }
182 else if ( obj->IsA()->InheritsFrom( "TTree" ) ) {
5
Taking false branch
11
Taking false branch
17
Taking false branch
183
184 // loop over all source files create a chain of Trees "globChain"
185 const char* obj_name= obj->GetName();
186
187 globChain = new TChain(obj_name);
188 globChain->Add(first_source->GetName());
189 TFile *nextsource = (TFile*)sourcelist->After( first_source );
190 // const char* file_name = nextsource->GetName();
191 // cout << "file name " << file_name << endl;
192 while ( nextsource ) {
193
194 globChain->Add(nextsource->GetName());
195 nextsource = (TFile*)sourcelist->After( nextsource );
196 }
197
198 } else if ( obj->IsA()->InheritsFrom( "TDirectory" ) ) {
6
Taking false branch
12
Taking false branch
18
Taking false branch
199 // it's a subdirectory
200
201 cout << "Found subdirectory " << obj->GetName() << endl;
202
203 // create a new subdir of same name and title in the target file
204 target->cd();
205 TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
206
207 // newdir is now the starting point of another round of merging
208 // newdir still knows its depth within the target file via
209 // GetPath(), so we can still figure out where we are in the recursion
210 MergeRootfile( newdir, sourcelist );
211
212 } else {
213
214 // object is of no type that we know or can handle
215 cout << "Unknown object type, name: "
216 << obj->GetName() << " title: " << obj->GetTitle() << endl;
217 }
218
219 // now write the merged histogram (which is "in" obj) to the target file
220 // note that this will just store obj in the current directory level,
221 // which is not persistent until the complete directory itself is stored
222 // by "target->Write()" below
223 if ( obj ) {
7
Taking true branch
13
Taking true branch
19
Taking true branch
24
Taking true branch
224 target->cd();
225
226 //!!if the object is a tree, it is stored in globChain...
227 if(obj->IsA()->InheritsFrom( "TTree" ))
8
Taking false branch
14
Taking false branch
20
Taking false branch
25
Taking true branch
228 globChain->Write( key->GetName() );
26
Called C++ object pointer is null
229 else
230 obj->Write( key->GetName() );
231 }
232
233 } // while ( ( TKey *key = (TKey*)nextkey() ) )
234
235 // save modifications to target file
236 target->Write();
237
238}
239
240