Reading objects that do not inherit from TObject (TArrayI)

Hi Wim,

Both in ROOT 5.30 and 5.28 I get crash when trying to read a TArrayI from a file (TFile).
Is this expected? Is there a workaround?

Thank you in advance,
Bruno

import ROOT
totalEvents = ROOT.TArrayI(1)
fout = ROOT.TFile('/tmp/test.root', 'recreate')
fout.WriteObject(totalEvents, 'totalEvents')
fout.Close()

fout = ROOT.TFile('/tmp/test.root')
fout.Get('totalEvents')

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================

Thread 2 (process 25503):
#0  0x00007fff867bdeb6 in __semwait_signal ()
#1  0x00007fff867c1cd1 in _pthread_cond_wait ()
#2  0x00000001000adcea in PyThread_acquire_lock ()
#3  0x00000001000852e4 in PyEval_RestoreThread ()
#4  0x0000000108cefff5 in _PyTime_DoubleToTimet ()
#5  0x0000000100089187 in PyEval_EvalFrameEx ()
#6  0x000000010008acce in PyEval_EvalCodeEx ()
#7  0x000000010002c88f in PyClassMethod_New ()
#8  0x000000010000aff3 in PyObject_Call ()
#9  0x000000010008a54e in PyEval_EvalFrameEx ()
#10 0x00000001000892e1 in PyEval_EvalFrameEx ()
#11 0x00000001000892e1 in PyEval_EvalFrameEx ()
#12 0x000000010008acce in PyEval_EvalCodeEx ()
#13 0x000000010002c8e1 in PyClassMethod_New ()
#14 0x000000010000aff3 in PyObject_Call ()
#15 0x000000010001a9df in PyClass_New ()
#16 0x000000010000aff3 in PyObject_Call ()
#17 0x00000001000849db in PyEval_CallObjectWithKeywords ()
#18 0x00000001000b1db6 in initthread ()
#19 0x00007fff867bc456 in _pthread_start ()
#20 0x00007fff867bc309 in thread_start ()

Thread 1 (process 25503):
#0  0x00007fff86800c90 in wait4 ()
#1  0x00007fff8681523e in system ()
#2  0x0000000106a1cd6c in TUnixSystem::StackTrace ()
#3  0x0000000106a19f11 in TUnixSystem::DispatchSignals ()
#4  <signal handler called>
#5  0x0000000100730147 in PyROOT::BindRootObject ()
#6  0x000000010071a162 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::CallSafe ()
#7  0x000000010071a316 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::Execute ()
#8  0x000000010071790c in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::operator() ()
#9  0x000000010071f23e in PyROOT::(anonymous namespace)::mp_call ()
#10 0x000000010000aff3 in PyObject_Call ()
#11 0x000000010008a51a in PyEval_EvalFrameEx ()
#12 0x000000010008acce in PyEval_EvalCodeEx ()
#13 0x000000010008ad61 in PyEval_EvalCode ()
#14 0x00000001000a265a in Py_CompileString ()
#15 0x00000001000a44dd in PyRun_InteractiveOneFlags ()
#16 0x00000001000a4615 in PyRun_InteractiveLoopFlags ()
#17 0x00000001000a4685 in PyRun_AnyFileExFlags ()
#18 0x00000001000b0286 in Py_Main ()
#19 0x0000000100000e6c in start ()
===========================================================


The lines below might hint at the cause of the crash.
If they do not help you then please submit a bug 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  0x0000000100730147 in PyROOT::BindRootObject ()
#6  0x000000010071a162 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::CallSafe ()
#7  0x000000010071a316 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::Execute ()
#8  0x000000010071790c in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::operator() ()
#9  0x000000010071f23e in PyROOT::(anonymous namespace)::mp_call ()
#10 0x000000010000aff3 in PyObject_Call ()
#11 0x000000010008a51a in PyEval_EvalFrameEx ()
#12 0x000000010008acce in PyEval_EvalCodeEx ()
#13 0x000000010008ad61 in PyEval_EvalCode ()
#14 0x00000001000a265a in Py_CompileString ()
#15 0x00000001000a44dd in PyRun_InteractiveOneFlags ()
#16 0x00000001000a4615 in PyRun_InteractiveLoopFlags ()
#17 0x00000001000a4685 in PyRun_AnyFileExFlags ()
#18 0x00000001000b0286 in Py_Main ()
#19 0x0000000100000e6c in start ()
===========================================================

Bruno,

create a null pointer of the right type (something like: ROOT.MakeNullPointer(ROOT.TArrayL) I think), then pass it to TFile.GetObject() which takes the name as usual and that null pointer (by reference).

Cheers,
Wim

Hi Wim,

Thanks, it works fine. Would it be possible to have it automatically in the future?

Thanks again,
Bruno

Bruno,

not sure how this could be done automatically: the C++ interface promises a TObject*, but then breaks that contract by returning something else. Since that “something else” is not defined, I can’t see how it can be checked or found out what it is in reality (effectively the TObject* is changed in a void* by breaking the contract). The only thing that can be done is not downcast the result, but that’d be a nuisance in most typical cases.

Besides, in the specific example that you have here, the crash is in the middle of TDirectory::Get() itself, so there is not even any return value to check or treat.

Cheers,
Wim

Hi,

this is no longer a problem in master:[code]>>> import ROOT

totalEvents = ROOT.TArrayI(1)
fout = ROOT.TFile(‘/tmp/test.root’, ‘recreate’)
fout.WriteObject(totalEvents, ‘totalEvents’)
67
fout.Close()
fout = ROOT.TFile(‘/tmp/test.root’)
fout.Get(‘totalEvents’).GetSize()
1
[/code]Cheers,
Wim