Bad behaviour of TArrayI::Set?

Dear ROOT friends,

I have encountered a problem with the TArrayI::Set method.
In my code, I have

  TArrayI *fBinPos[2];

defined somewhere. Then I have a method to fill this array, it looks like this (print statements for debugging):

void TXaImage::SetBinPosArray(const EXaCoord crd,
			      const Int_t nPos, 
			      const Int_t binPos[])
{
  cout << "before nPos = " <<  nPos  << endl;
  cout << "before binPos[0] = " <<  binPos[0]  << endl;
  cout << "before binPos[1] = " <<  binPos[1]  << endl;
  cout << "before binPos[2] = " <<  binPos[2]  << endl;
  
  fBinPos[crd]->Set(nPos,binPos);

  cout << "after nPos = " <<  nPos  << endl;
  cout << "after binPos[0] = " <<  binPos[0]  << endl;
  cout << "after binPos[1] = " <<  binPos[1]  << endl;
  cout << "after binPos[2] = " <<  binPos[2]  << endl;

  fNBinPos[crd] = nPos;
}

Now there are situations where I get the following output from the above cout statments:

before nPos = 11
before binPos[0] = 144
before binPos[1] = 171
before binPos[2] = 199
after nPos = 11
after binPos[0] = 0
after binPos[1] = 171
after binPos[2] = 199

In other words, the Set method messes up the array I supply! Why and how can that happen?

Any ideas are welcome.

Cheers,

Thomas

Hi,

Set does not modify the array parameter itself. It deletes its own fArray - and if that is the same as the array parameter then you are in trouble as see what you might have seen. As the doc says: “// This function should not be called if the array was declared via Adopt.”

Actually it should be trivial to check whether fArray == array (really whether the two pointers are identical), in which case Set() should simply return. We will let you know. Either way: make sure the array you pass to Set has not been Adopt()ed (or assigned to the public member fArray) before.

Cheers, Axel.

Hi Axel,

thanks for the prompt advice, which helped me find my problem quickly.
I was not using Adopt anywhere (I did read the documentation), but I was updating my TArrayI by first reading out the array with

  *binPos = &fBinPos[crd]->GetArray()[0];

then doing something to the array and returning it to the TArrayI with

  fBinPos[crd]->Set(nPos,binPos);

which is a bad thing to do I realize now!

I am surprised at the very subtle manifestation of this mistake: only one element is quietly set to zero, everything else looks just the same. I only found out about this by accident!

Many thanks again,

Thomas