Segfault with AddBinContent but not with Fill

I’m trying to rebin the axis of a 2D histogram, by repopulating a new histogram with AddBinContent. I’m getting segfaults, which are weird because it doesn’t seem to crash at the same line in the code each time I run, and the stack traces come out different. I post one of those stack traces at the bottom.

The code runs fine if I replace the AddBinContent with Fill. I attach the code and a file to run on to reproduce the problem. I tried both root 5.34.25 and 6.02.10. I’m doing these operations inside a larger script, and running that just causes the program to freeze.
smallfile.root (130 KB)

from ROOT import *
from array import array

def rebinX(histlist):
    ''' Rebin 2D histos in x according to a custom hard-coded
        binning as specified in getCustomXbins() 
        Uses Rene's suggestion here https://root-forum.cern.ch/t/th2f-histogram-rebinning-with-different-bin-sizes/5796/1
        except uses AddBinConent instead of Fill to get proper errors, which also requires
        SetEntries to be called. Sumw2 has to be called after all of this. 
    '''
    # custom pt bins
    print "getting custom x bins..."
    (nbins_x, xbins) = getCustomXbins()
    histlist_rebinned = []
    for hist in histlist:
        xaxis = hist.GetXaxis()
        yaxis = hist.GetYaxis()
        hname = hist.GetName()+'_RebinX'
        h_rebinned = TH2D(hname, hist.GetTitle(), nbins_x, xbins, yaxis.GetNbins(), yaxis.GetXmin(), yaxis.GetXmax())
        h_rebinned.Sumw2(kFALSE)

        # populate new histogram
        print "populating new rebinned histo..."
        for xbin in range(1, xaxis.GetNbins()+1):
            for ybin in range(1, yaxis.GetNbins()+1):
                # To use AddBinContent the global bin nr must be found
                x = xaxis.GetBinCenter(xbin)
                y = yaxis.GetBinCenter(ybin)
                ### If AddBinContent is replaced by Fill, segfault is no longer present
                h_rebinned.AddBinContent(hist.FindBin(x, y), hist.GetBinContent(xbin, ybin))

        print "Done populating, now calling SetEntries and Sumw2 before appending to new histlist"
        h_rebinned.SetEntries(hist.GetEntries())
        h_rebinned.Sumw2()
        histlist_rebinned.append(h_rebinned)

    return histlist_rebinned

def getCustomXbins():
    nbins_x_custom = 37 
    array_x_custom = [0.]*(nbins_x_custom+1)
    for b in range(6+1):   array_x_custom[b   ] = 0.1  + b*0.025;
    for b in range(5+1):   array_x_custom[b+6 ] = 0.25 + b*0.05;
    for b in range(20+1):  array_x_custom[b+11] = 0.5  + b*0.1;
    for b in range(4+1):   array_x_custom[b+31] = 2.5  + b*0.250;
    for b in range(1+1):   array_x_custom[b+35] = 3.5  + b*0.5;
    array_x_custom[37] = 200.
    return (nbins_x_custom, array('d',array_x_custom))

#### RUN SCRIPT

# open file and get histos
file = TFile.Open("smallfile.root", "READ")
h1 = file.Get("SelectedMigratedPtPrimaryTracks_PtEta")
h2 = file.Get("SelectedMigratedEtaPrimaryTracks_PtEta")
h3 = file.Get("MigratedOutPtPrimaryTruthTracks_PtEta")
h4 = file.Get("SelectedTracks_PtEta")

histlist = [h1,h2,h3,h4]
for hist in histlist: hist.SetDirectory(0)
file.Close()

print "Getting hists with rebinned x axis."
histlist = rebinX(histlist)

An example of a segfault

[code]===========================================================
#6 0x00007f26d331170c in clang::CodeGen::CodeGenModule::EmitTargetMetadata() () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#7 0x00007f26d2e28fea in cling::IncrementalParser::codeGenTransaction(cling::Transaction*) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#8 0x00007f26d2e28d8f in cling::IncrementalParser::commitTransaction(cling::Transaction*) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#9 0x00007f26d2e2b0d4 in cling::IncrementalParser::Compile(llvm::StringRef, cling::CompilationOptions const&) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#10 0x00007f26d2dd7779 in cling::Interpreter::DeclareInternal(std::basic_string<char, std::char_traits, std::allocator > const&, cling::CompilationOptions const&, cling::Transaction**) const () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#11 0x00007f26d2dd78b8 in cling::Interpreter::declare(std::basic_string<char, std::char_traits, std::allocator > const&, cling::Transaction**) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#12 0x00007f26d2dd7979 in cling::Interpreter::DeclareCFunction(llvm::StringRef, llvm::StringRef, bool) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#13 0x00007f26d2dd7f2f in cling::Interpreter::compileFunction(llvm::StringRef, llvm::StringRef, bool, bool) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#14 0x00007f26d2d4f316 in TClingCallFunc::compile_wrapper(std::basic_string<char, std::char_traits, std::allocator > const&, std::basic_string<char, std::char_traits, std::allocator > const&, bool) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#15 0x00007f26d2d51aab in TClingCallFunc::make_wrapper() () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#16 0x00007f26d2d557e0 in TClingCallFunc::IFacePtr() () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#17 0x00007f26d2d55822 in TClingCallFunc::Exec(void*, TInterpreterValue*) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libCling.so
#18 0x00007f26d9dfb9d5 in PyROOT::TVoidExecutor::Execute(CallFunc_t*, void*, bool) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libPyROOT.so
#19 0x00007f26d9dfb3f0 in PyROOT::TMethodHolder::CallSafe(void*, bool) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libPyROOT.so
#20 0x00007f26d9df947d in PyROOT::TMethodHolder::Execute(void*, bool) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libPyROOT.so
#21 0x00007f26d9df8b72 in PyROOT::TMethodHolder::operator()(PyROOT::ObjectProxy*, _object*, _object*, long, bool) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libPyROOT.so
#22 0x00007f26d9de550d in PyROOT::(anonymous namespace)::mp_call(PyROOT::MethodProxy*, _object*, _object*) () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/libPyROOT.so
#23 0x00007f26e11c7703 in PyObject_Call () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/bin/…/lib/libpython2.7.so.1.0
#24 0x00007f26e127a2a1 in PyEval_EvalFrameEx () at /build/hegner/afs_build/lcgcmake-build/externals/Python/src/Python/2.7.4/Python/ceval.c:4239
#25 0x00007f26e127e5ed in PyEval_EvalCodeEx () at /build/hegner/afs_build/lcgcmake-build/externals/Python/src/Python/2.7.4/Python/ceval.c:3253
#26 0x00007f26e11f91b5 in function_call () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/bin/…/lib/libpython2.7.so.1.0
#27 0x00007f26e11c7703 in PyObject_Call () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/bin/…/lib/libpython2.7.so.1.0
#28 0x00007f26e1279976 in PyEval_EvalFrameEx () at /build/hegner/afs_build/lcgcmake-build/externals/Python/src/Python/2.7.4/Python/ceval.c:4334
#29 0x00007f26e127e5ed in PyEval_EvalCodeEx () at /build/hegner/afs_build/lcgcmake-build/externals/Python/src/Python/2.7.4/Python/ceval.c:3253
#30 0x00007f26e11f90e0 in function_call () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/bin/…/lib/libpython2.7.so.1.0
#31 0x00007f26e11c7703 in PyObject_Call () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/bin/…/lib/libpython2.7.so.1.0
#32 0x00007f26e1277f87 in PyEval_CallObjectWithKeywords () at /build/hegner/afs_build/lcgcmake-build/externals/Python/src/Python/2.7.4/Python/ceval.c:3890
#33 0x00007f26e12a9bf7 in Py_Finalize () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/bin/…/lib/libpython2.7.so.1.0
#34 0x00007f26e12bf725 in Py_Main () from /cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/bin/…/lib/libpython2.7.so.1.0
#35 0x00007f26e0558d5d in __libc_start_main () from /lib64/libc.so.6
#36 0x00000000004006d9 in _start ()

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File “/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/lib/python2.7/atexit.py”, line 24, in _run_exitfuncs
func(*targs, **kargs)
File “/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/ROOT.py”, line 663, in cleanup
gROOT.EndOfProcessCleanups()
SystemError: void TROOT::EndOfProcessCleanups() =>
problem in C++; program state has been reset
Error in sys.exitfunc:
Traceback (most recent call last):
File “/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/python/2.7.4-x86_64-slc6-gcc48/sw/lcg/external/Python/2.7.4/x86_64-slc6-gcc48-opt/lib/python2.7/atexit.py”, line 24, in _run_exitfuncs
func(*targs, **kargs)
File “/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/root/6.02.10-x86_64-slc6-gcc48-opt/lib/ROOT.py”, line 663, in cleanup
gROOT.EndOfProcessCleanups()
SystemError: void TROOT::EndOfProcessCleanups() =>
problem in C++; program state has been reset
[/code]

Hi,

this line:h_rebinned.AddBinContent(hist.FindBin(x, y), hist.GetBinContent(xbin, ybin))will index the array position of bin “hist.FindBin(x, y)” in h_rebinned. But your getCustomXbins() made sure that the the nr. of xbins for h_rebinned is smaller than that for hist, so your indexing random memory. Don’t do that.

Cheers,
Wim