Home | News | Documentation | Download

Error in <TRefArray::AddAtAndExpand>

So I have this stand alone program that collects data and writes it to a root file. It seems to run fine for the most part, but recently when it was collecting a large chunk of data, I started seeing this spewing:

Error in TRefArray::AddAtAndExpand: The object at 0x24f0c90 is not registered in the process the TRefArray point to (pid = ProcessID0/30388770-e7cf-11e1-9717-c3bda8c0beef)

I had to abort the executable since there was no end to the spewing. Now accord to the classTRefArray document, it states the following:

[quote]By default the TRefArray ‘points’ to the current process and can only
receive object that have been created in this process.
To point the TRefArray to a different process do:
TRefArray array( processId );

For example, if ‘obj’ is an instance that was created in the different
process and you do:
TRefArray array( TProcessID::GetProcessWithUID( obj ) );
Then
array.Add(obj);
is correct (obj comes from the process the array is pointed to
while
TObject *nobj = new TObject;
array.Add(nobj);
is incorrect since ‘nobj’ was created in a different process than the
one the array is pointed to. In this case you will see error message:
Error in TRefArray::AddAtAndExpand: The object at 0x… is not
registered in the process the TRefArray point to
(pid = ProcessID…/…)[/quote]

But I’m only running one process (not multi-threaded), so I’m not sure why this is spewing … and it only seems to spew when it’s collecting a very large data set. It is true that use the default TRefArray (not passing the process id), but I didn’t think I needed to since the code is only running in one process… am I doing something wrong? Or is the complaint referring to something else?

OK, I figured out this problem. From the example given in the Event::build found in the tutorials directory, when looping over events (that involves TRefs), one needs to set this:

[code]
//Save current Object count
Int_t ObjectNumber = TProcessID::GetObjectCount();
… fill event buffer

//Restore Object count
//To save space in the table keeping track of all referenced objects
//we assume that our events do not address each other. We reset the
//object count to what it was at the beginning of the event.
TProcessID::SetObjectCount(ObjectNumber);[/code]

Apparently this is only needed in the standalone executables (???); never seen that this was done in any of the macro examples I’ve seen.

The explanation is found here, where it states:

[quote]Object Number

When an object is referenced, a unique identifier is computed and stored in both the fUniqueID of the referenced and referencing object. This uniqueID is computed by incrementing by one the static global in TProcessID::fgNumber. The fUniqueID is the serial object number in the current session. One can retrieve the current fgNumber value by calling the static function TProcessID::GetObjectCount at any time or can set this number by TProcessID::SetObjectCount. To avoid a growing table of fObjects in TProcessID, in case, for example, one processes many events in a loop, it might be necessary to reset the object number at the end of processing of one event. See an example in $ROOTSYS/test/Event.cxx (look at function Build). The value of ObjectNumber may be saved at the beginning of one event and reset to this original value at the end of the event. These actions may be nested.

saveNumber = TProcessID::GetObjectCount();

TProcessID::SetObjectCount(savedNumber);[/quote]

I can’t say I quite understand that :confused: , but it seems to fix the problem I was observing for large data sets.