Problem in TGraphPainter [was:TCutG problem in qtroot]

Dear rooters,

I am trying to use TCutG in a qt-based application using ROOT functionalities. I am attaching a hopefully minimal example to reproduce the problem.
What I am trying to do is the following: Up clicking a button, a TCutG object is created with fixed dimensions. The user can move this object to his liking and then adds to/subtracts from the current selection.

The problem is that there seems to be memory corruption when one moves the individual TCutG points, frequently resulting in double free(), corrupted pointer or other messages.

In the program flow, the crash occurs when trying to delete the TCutG object after pressing the ‘select’ button. Some memory checking hints at memory corruption occurring when TGraphPainter::ExecuteEventHelper is executed, but it’s not clear if this method is actually the cause of the problem

Any hint on this issue is gladly appreciated, also if what I am doing is conceptually impossible or an improper use of the TCutG functionality.

Best regards,

tcutgexample.tar.gz (384 KB)

Hello again,

I think I found the solution to my problem. The issue is that there is a small weakness in the TGraphPainter::ExecuteEventHelper method. The problem occurs when the canvas window does not have the focus and the user performs his/her first click next to the line (but not a point!) of the TCutG before bringing the canvas window into focus.
This will result in the first two actions being:

which will set:

and not change it to anything else since the pointer is not close to any of the graph points.

if this occurs directly after the drawing of the TCutG, middle will still be false, and it will only be set to true once:

has been processed, which will not be done since the window doesn’t have focus.
Therefore the

    if (middle) {
         for(i=0;i<theNpoints;i++) {
            if (badcase) continue;  //do not update if big zoom and points moved
            if (x) theX[i] = gPad->PadtoX(gPad->AbsPixeltoX(x[i]+dpx));
            if (y) theY[i] = gPad->PadtoY(gPad->AbsPixeltoY(y[i]+dpy));
      } else {
         theX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold));
         theY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold));

condition will be evaluated to execute:

and since ipoint == -1 this results in memory corruption.

Let me stress that this problem occurs irrespective of the usage of qt, I was able to reproduce exactly the same behavior by constructing a TCutG via the command line and click into a ‘out-of-focus’ canvas window.

A possible solution could be to initialize middle = 1 or
put a small if around the method to set theX

if( ipoint > -1 ) {
 theX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold));
 theY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold));

Please let me know what you think



What have you done exactly to reproduce this problem outside the Qt environment ?


indeed I found that while I was able to reproduce the problem in one situation (which was using a machine which I need to access via a ssh tunnel, I later found that I was not easily able to reproduce the problem locally on my machine.

What I did was:
I had an ssh connection open to the other machine, I opened root and then simply did:

    TH1F *h1 = new TH1F("h1","Histo",100,-1,1);
    float x[5] = {-0.8,0.8,0.8,-0.8,-0.8};
    float y[5] = {30,30,70,70,30};
    TCutG *cut = new TCutG("cut",5,x,y);

the canvas windows was in the background for this and when then moving the mouse over the canvas window, the mouse move events, it seems, were not properly forwarded. When I then clicked on the cut line, this brought the window into focus and I saw (using debug statements) that the code would have called theX[-1].

It seems that if you see the problem or not depends on how exactly X events are forwarded or not to a non-active window. I saw that my mouse pointer did not change shape when it was near the lines as it should be the case if the events are forwarded properly. And so as I described if the first signals received by the canvas window happen to be a combination of kButton1Down followed by kButton1Up, the code can run into problems.

Let me know if you need any more information.