TTree::Fill() causes program to wet itself, segfault

My code causes a seg fault that I am sure is the result of an initialized pointer somewhere. However, I have checked thoroughly and cannot find any pointers that are initialized improperly. Am I somehow calling fill() incorrectly?

I’ve run it through gdb and the debugger identifies the problems as being at the combdata->Fill() line, line 345. I have taken many debugging steps, the most interesting of which is commenting out any of the code that assigns anything to the tree combdata, and yet I still get a segfault.

The code otherwise functions normally until it gets to the fill line.

My code is below, any help would be greatly appreciated. Thanks in advance!

/* 
Program in C to combine TPFit data and GBT data into one file based on the BCIDS
Written by Joseph Farah on June 19, 2017
Last updated by [Joseph Farah] on: [June 21, 2017]

Notes
- for some reason this code causes the root intepreter to segfault when .q is run
- if you do it (type .q) twice the problem just goes away
- how to print anythin that has type vector<int>: use * upon declaration and get
	value with gbtMMFE8->at(0)
- 
*/

// header imports
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <TROOT.h>
#include <TChain.h>
#include <TFile.h>
#include "TSystem.h"

#define TRUE 1
#define FALSE 0

// begin main function 
int main( int argc, char *argv[] )
{
	// check the number of args, it should be 3 for proper execution
	// there will always be 4 args because the file name is the first arg
	if( argc != 4 ) { std::cout << argv[0] << " needs three args" << std::endl; return 0; }

	// make all the filename strings constants to use in the TFile constructor
	const char* gfile = argv[1];
	const char* tfile = argv[2];
	const char* ofile = argv[3];

	std::cout << gfile << std::endl << tfile << std::endl << ofile << std::endl;

	// initialize the GBT file using TFile and using the GBT file as the argument
	// create new fileobject for GBT
	TFile *gbt_file_object = new TFile(gfile);
	// pull the tree from the file
	TTree *gbt_tree = (TTree*)gbt_file_object->Get("GBT_data");
	
	// do the same thing now with the TPfit file
	// create new file object for TPfit
	TFile *tpfit_file_object = new TFile(tfile);
	// pull the tpfit tree fromt he file
	TTree *tpfit_tree = (TTree*)tpfit_file_object->Get("TPfit_data");

	// get the number of all the entries in both of the trees
	long ngbt = gbt_tree->GetEntries();
	long nfit = tpfit_tree->GetEntries();

	// create the output file, overwriting the old one if necessary
	TFile *output_file = new TFile(ofile, "RECREATE");

	// here i'm going to start creating the branches for the new file
	// this is going to require me initiliazing various variables to use
	// as addresses, a TTree, and the branches themsleves
	int 				t_eventnum;
	int 				t_cntr;
	int 				t_timesec;
	int 				t_timensec;
	int 				t_bcid;
	int 				t_mxlocal;
	int 				t_tpfit_n;
	std::vector<int> 	*t_tpfit_VMM = 0;
	std::vector<int> 	*t_tpfit_CH = 0;
	std::vector<int> 	*t_tpfit_MMFE8 = 0;
	std::vector<int> 	*t_tpfit_BCID = 0;

	// this will create the combined branches data tree
	// argument setup: Branch(branchname address, leaflist)
	// for vectors, use the address of the vector instead of the name
	TTree *combdata = new TTree("TPcomb_data", "TPcomb_data");
	combdata->Branch("EventNum", t_eventnum, "EventNum/I");
    combdata->Branch("cntr",  t_cntr, "cntr/I");
    combdata->Branch("Time_sec",  t_timesec, "Time_sec/I" );
    combdata->Branch("Time_nsec",  t_timensec, "Time_nsec/I");    
    combdata->Branch("BCID",  t_bcid, "BCID/I");
    combdata->Branch("mxlocal", t_mxlocal, "mxlocal/F");
    combdata->Branch("tpfit_VMM", &t_tpfit_VMM);
    combdata->Branch("tpfit_CH", &t_tpfit_CH);
    combdata->Branch("tpfit_MMFE8", &t_tpfit_MMFE8);
    combdata->Branch("tpfit_BCID", &t_tpfit_BCID);
    combdata->Branch("tpfit_n",t_tpfit_n, "tpfit_n/I");

    // get the addresses of all the branches in the GBT and TPFit trees
    //gbt tree address declaration
    int 				gbtTime_sec;
    int 				gbtTime_nsec;
    std::vector<int> 	*gbtMMFE8 = 0;
    std::vector<int> 	*gbt_VMM = 0;
    std::vector<int> 	*gbt_CH = 0;
    std::vector<int>	*gbt_BCID = 0;

       // List of branches
    TBranch        *b_EventNum = 0;   //!
    TBranch        *b_Time_sec = 0;   //!
    TBranch        *b_Time_nsec = 0;   //!
    TBranch        *b_gbt_VMM = 0;   //!
    TBranch        *b_gbt_CH = 0;   //!
    TBranch        *b_gbt_MMFE8 = 0;   //!
    TBranch        *b_gbt_BCID = 0;   //!

   //gbt_tree->SetMakeClass(1);

    // gbt_tree->SetBranchAddress("Time_sec", &gbtTime_sec);
    // gbt_tree->SetBranchAddress("Time_nsec", &gbtTime_nsec);
    // gbt_tree->SetBranchAddress("gbt_MMFE8", &gbtMMFE8);
    // gbt_tree->SetBranchAddress("gbt_VMM", &gbt_VMM);
    // gbt_tree->SetBranchAddress("gbt_CH", &gbt_CH);
    // gbt_tree->SetBranchAddress("gbt_BCID", &gbt_BCID);
   gbt_tree->SetBranchAddress("Time_sec", &gbtTime_sec, &b_Time_sec);
   gbt_tree->SetBranchAddress("Time_nsec", &gbtTime_nsec, &b_Time_nsec);
   gbt_tree->SetBranchAddress("gbt_VMM", &gbt_VMM, &b_gbt_VMM);
   gbt_tree->SetBranchAddress("gbt_CH", &gbt_CH, &b_gbt_CH);
   gbt_tree->SetBranchAddress("gbt_MMFE8", &gbtMMFE8, &b_gbt_MMFE8);
   gbt_tree->SetBranchAddress("gbt_BCID", &gbt_BCID, &b_gbt_BCID);


    //tpfit tree address declaration
    int EventNum, nevent;
    int tpTime_sec;
    int tpTime_nsec;
    int BCID, bcid;
    float mxlocal, mxloc;
    int tpfit_n, nhit;
    int cntr, spec_cntr;
    std::vector<int>    *tpfit_MMFE8 = 0;
    std::vector<int>    *tpfit_VMM = 0;
    std::vector<int>    *tpfit_CH = 0;

    tpfit_tree->SetBranchAddress("EventNum", &EventNum);
    tpfit_tree->SetBranchAddress("Time_sec", &tpTime_sec);
    tpfit_tree->SetBranchAddress("Time_nsec", &tpTime_nsec);
    tpfit_tree->SetBranchAddress("BCID", &BCID);
    tpfit_tree->SetBranchAddress("mxlocal", &mxlocal);
    tpfit_tree->SetBranchAddress("tpfit_n", &tpfit_n);
    tpfit_tree->SetBranchAddress("cntr", &cntr);
    tpfit_tree->SetBranchAddress("tpfit_MMFE8", &tpfit_MMFE8);
    tpfit_tree->SetBranchAddress("tpfit_VMM", &tpfit_VMM);
    tpfit_tree->SetBranchAddress("tpfit_CH", &tpfit_CH);

    // initialize any variables that will be used within the loop
    float gbttime;
    float tpfittime;
    float time_difference;
    int i = 0;
    int num_changes_per_loop = 1;
    int counter = 0;
    int j;
    int currifitpk = 0;
    int tmpcount = 0;
    int tsize, gsize;
    // vectors that need to be created that will hold everything
    const int GBT_COORDINATE_LENGTH = 9;
    std::vector<int> gbtmmfes = {};
    std::vector<int> gbtvmms = {};
    std::vector<int> gbtchs = {};
    std::vector<int> gbtbcids = {};

    std::vector<int> tpmmfes ={};
    std::vector<int> tpvmms = {};
    std::vector<int> tpchs = {};
    std::vector<int> tpbcids = {};

    // this vector will store the hit information for each track
    // use i to compare to the gbt data
    std::vector<int> tp_tmp_hit_storage = {};
    std::vector<int> gbt_tmp_hit_storage = {};
    int boards[] = {118,116,102,119,106,107,117,105};
    //loop through the GBT set
    tpfit_tree->Print();



    i = 0;


    while(gbt_tree->GetEntry(i))
    {
        gbtmmfes.clear();
        gbtvmms.clear();
        gbtchs.clear();
        gbtbcids.clear();
        // get the exact tiem of the event in nanoseconds by adding the time
        // in seconds to the time in nanoseconds
        gbttime = gbtTime_sec + gbtTime_nsec/pow(10.,9);
        // if the time exceeds a certain limit, break
        // eventually when we're out of the testing phase we'll remove the i limitation
        if(i >=1000 || gbttime > 1495040000) { std::cout << "done" << std::endl;break; }
        /* creating a list containing the coordinates for each part of the event*/
        for(counter = 0; counter < 10; counter++)
        {
            try {gbtmmfes.push_back(gbtMMFE8->at(counter));}
            catch (std::out_of_range& e) { break;}
            // gbtmmfes.push_back(gbtMMFE8->at(counter));
            gbtvmms.push_back(gbt_VMM->at(counter));
            gbtchs.push_back(gbt_CH->at(counter));
            gbtbcids.push_back(gbt_BCID->at(counter));
            //std::cout << gbt_BCID->at(counter) << std::endl;

        }
        counter = 0;
        //std::cout << gbtbcids.size() << std::endl;
        // sort all the arrays by size
        // this bit of code is a bubblesort, and it also sorts the other arrays
        // by the same rule as the mmfe8 so that  they remain aligned
        while(counter++<GBT_COORDINATE_LENGTH)
        {
            if(num_changes_per_loop==0) { break; }
            for(int counter1=0;counter1<gbtmmfes.size();counter1++)
            {
                int current_value = gbtmmfes[counter1];
                int adjacent_value = gbtmmfes[counter1+1];
                if(adjacent_value > current_value) {;}
                else if(current_value > adjacent_value) {
                    int tmp = adjacent_value;
                    std::swap(gbtmmfes[counter1], gbtmmfes[counter1+1]);
                    std::swap(gbtvmms[counter1], gbtvmms[counter1+1]);
                    std::swap(gbtchs[counter1], gbtchs[counter1+1]);
                    std::swap(gbtbcids[counter1], gbtbcids[counter1+1]);
                    num_changes_per_loop++;
                }
            }
        }

        // check to see if there are any boards that did not fire, if thats the case
        // replace their values with zeros by adding a new "event" to the array
        for(counter=0; counter<7; counter++)
        {
            int *tmpaddress = std::find(std::begin(boards),std::end(boards), boards[counter]);
            if( tmpaddress==std::end(boards) )
            {
                gbtmmfes.push_back(boards[counter]);
                gbtvmms.push_back(0);
                gbtchs.push_back(0);
                gbtbcids.push_back(0);
                std::cout << "Padded" << std::endl;
            }
        }
        // for(int k=0; k<gbtbcids.size(); k++)
        // {
        //     std::cout << gbtbcids[k] << std::endl;
        // }
        j = currifitpk;
        while(TRUE) {
            //get trigger process across #j, whatever j happens to be
            int nmatch = 0;
            tpfit_tree->GetEntry(j);
            tpmmfes.clear();
            tpvmms.clear();
            tpchs.clear();
            tpbcids.clear();

            // if j is greater than the number of things in the fit tp file, break the loop
            if( j == nfit ) { break; }
            // start declaring all the track information from tpfittree
            nevent = EventNum;
            tpfittime = tpTime_sec + tpTime_nsec/pow(10.,9);
            bcid = BCID;
            mxloc = mxlocal;
            nhit = tpfit_n;
            spec_cntr = cntr;
            for(counter = 0; counter < 10; counter++)
            {
                try {tpmmfes.push_back(tpfit_MMFE8->at(counter));}
                catch (std::out_of_range& e) { break;}
                tpmmfes.push_back(tpfit_MMFE8->at(counter));
                tpvmms.push_back(tpfit_VMM->at(counter));
                tpchs.push_back(tpfit_CH->at(counter));

            }

            // check the time difference betwen the tp and gbt packet
            // they should ideally be very close together, some difference is acceptable
            // but if the difference is greater than 0.2 we are misaligning the data
            time_difference = tpfittime - gbttime;;
            // break if we've gone to far
            if( time_difference>0.2 ) { break; }
            // if the time difference between the tp packet and the gbt packet
            // is within reasonable error, do the following
            time_difference = abs(time_difference);
            if( time_difference<0.2 )
            {
                // std::cout << "yay" << std::endl;
                // is the time of the tpfit packet in the list of the gbt packet BCIDS
                // we created earlier? if so, continue
                if( std::find(gbtbcids.begin(), gbtbcids.end(), bcid) != gbtbcids.end() )
                {
                    std::cout << "The value " << bcid << " was found in the GBT packet" << std::endl;
                    // fill a vector with the single hit information to compare to the gbt stuff
                    for(int counter1=0; counter1<gbtmmfes.size(); counter1++)
                    {
                        gbt_tmp_hit_storage.clear();
                        gbt_tmp_hit_storage.push_back(gbtmmfes[counter1]);
                        gbt_tmp_hit_storage.push_back(gbtvmms[counter1]);
                        gbt_tmp_hit_storage.push_back(gbtchs[counter1]);
                        gsize = gbt_tmp_hit_storage.size();
                        //std::cout << "gsize " << gsize << std::endl;    
                        for(int counter2=0; counter2<tpmmfes.size(); counter2++)
                        {
                            tp_tmp_hit_storage.clear();
                            tp_tmp_hit_storage.push_back(tpmmfes[counter2]);
                            tp_tmp_hit_storage.push_back(tpvmms[counter2]);
                            tp_tmp_hit_storage.push_back(tpchs[counter2]);
                            gsize = gbt_tmp_hit_storage.size();
                            tsize = tp_tmp_hit_storage.size();
                            //std::cout << "gsize and tsize " << gsize << " " << tsize << std::endl;
                            // are the coordinates int eh gbt set the same as the 
                            // coordinates recorded by the trigger process? if yes
                            // continue, if no, don't do anything
                            if( gbt_tmp_hit_storage == tp_tmp_hit_storage )
                            {
                                // increment nmatch too add to the lsit of entries
                                // that have corresponding trigger events
                                nmatch += 1;
                                t_tpfit_MMFE8->push_back(tpmmfes[counter2]);
                                t_tpfit_VMM->push_back(tpvmms[counter2]);
                                t_tpfit_CH->push_back(tpchs[counter2]);
                                t_tpfit_BCID->push_back(gbtbcids[counter1]);
                                tmpcount = counter1;
                            }
                        }

                    }
                    // update the combined branches with all the new data
                    t_mxlocal = mxloc;
                    t_bcid = gbtbcids[tmpcount];
                    t_tpfit_n = nhit;
                    t_cntr = spec_cntr;
                    t_eventnum = nevent;
                    t_timesec = tpTime_sec;
                    t_timensec = tpTime_nsec;
                    std::cout << nmatch << " " << nhit << std::endl;

                    if( nmatch == nhit )
                    {
                        currifitpk = j + 1;
                        gDebug=1;
                        combdata->Fill();
                        std::cout << "FILLED FILLED FILLED" << std::endl;
                    }
                    t_tpfit_MMFE8->clear();
                    t_tpfit_VMM->clear();
                    t_tpfit_CH->clear();
                    t_tpfit_BCID->clear();
                }
            }
            j++;


        } 

    	i++;
}

        // // this is a test print funciton, im going to leave it for now
     //        // for(int counter = 0; counter < GBT_COORDINATE_LENGTH; counter++)
        // // {
        // //   std::cout << gbtmmfes[counter] << std::endl;
        // // }
     //        j++;

     //    }
    output_file->Write();
    output_file->Close();


	return 0;
}

And the error, including the output of gDebug:

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007f174b78e4ca in __GI___waitpid (pid=12434, stat_loc=stat_loc
entry=0x7fff94d53380, options=options
entry=0) at ../sysdeps/unix/sysv/linux/waitpid.c:29
#1  0x00007f174b707fbb in do_system (line=<optimized out>) at ../sysdeps/posix/system.c:148
#2  0x00007f174cb02064 in TUnixSystem::StackTrace() () from /home/vhx/Documents/root/lib/libCore.so
#3  0x00007f174cb046cc in TUnixSystem::DispatchSignals(ESignals) () from /home/vhx/Documents/root/lib/libCore.so
#4  <signal handler called>
#5  0x00007f174c486f40 in TBufferFile::WriteFastArray(int const*, int) () from /home/vhx/Documents/root/lib/libRIO.so
#6  0x00007f174c0d990c in TBranch::FillLeavesImpl(TBuffer&) () from /home/vhx/Documents/root/lib/libTree.so
#7  0x00007f174c0dcd8a in TBranch::Fill() () from /home/vhx/Documents/root/lib/libTree.so
#8  0x00007f174c10bf09 in TTree::Fill() () from /home/vhx/Documents/root/lib/libTree.so
#9  0x0000000000405126 in main (argc=4, argv=0x7fff94d56328) at combineTPGBT_standalone.c:345
===========================================================


The lines below might hint at the cause of the crash.
You may get help by asking at the ROOT forum http://root.cern.ch/forum.
Only if you are really convinced it is a bug in ROOT then please submit a
report at http://root.cern.ch/bugs. Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#5  0x00007f174c486f40 in TBufferFile::WriteFastArray(int const*, int) () from /home/vhx/Documents/root/lib/libRIO.so
#6  0x00007f174c0d990c in TBranch::FillLeavesImpl(TBuffer&) () from /home/vhx/Documents/root/lib/libTree.so
#7  0x00007f174c0dcd8a in TBranch::Fill() () from /home/vhx/Documents/root/lib/libTree.so
#8  0x00007f174c10bf09 in TTree::Fill() () from /home/vhx/Documents/root/lib/libTree.so
#9  0x0000000000405126 in main (argc=4, argv=0x7fff94d56328) at combineTPGBT_standalone.c:345
===========================================================


Info in <TFile::WriteStreamerInfo>: called for file combinedtest.root
   TKey Writing 85 bytes at address 230 for ID= StreamerInfo Title= Doubly linked list
   TKey Writing 55 bytes at address 315 for ID= combinedtest.root Title= 
   TKey Writing 61 bytes at address 370 for ID= combinedtest.root Title= 
Info in <TFile::~TFile>: dtor called for datafiles/Run3522_GBT_decoded.root [24dcba0]
Info in <TDirectoryFile::~TDirectoryFile>: dtor called for datafiles/Run3522_GBT_decoded.root
Info in <TDirectory::~TDirectory>: dtor called for datafiles/Run3522_GBT_decoded.root
Info in <TFile::~TFile>: dtor called for datafiles/Run3522_FIT_decoded.root [3b01f90]
Info in <TDirectoryFile::~TDirectoryFile>: dtor called for datafiles/Run3522_FIT_decoded.root
Info in <TDirectory::~TDirectory>: dtor called for datafiles/Run3522_FIT_decoded.root
Info in <TFile::~TFile>: dtor called for combinedtest.root [3af9790]
Info in <TDirectoryFile::~TDirectoryFile>: dtor called for combinedtest.root
Info in <TDirectory::~TDirectory>: dtor called for combinedtest.root

Try replacing the lines like:

combdata->Branch("Time_sec",  t_timesec, "Time_sec/I" );

with

combdata->Branch("Time_sec",  &t_timesec, "Time_sec/I" );

or even

combdata->Branch("Time_sec",  &t_timesec );

Cheers,
Philippe.

1 Like

pcanal, you’re a genius. Thank you so much!! That worked!

You are welcome. Cheers, Philippe.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.