I have a software where I receive a new histogram on a regular basis. I must display it in a TCanvas.
My problem is that users start to interact with the canvas and with the histo while the update occurs. During the update I replace the displayed histo, and this leads to a crash because the action of the user spanned over the update. I guess that it tries to do something on the former histogram which no longer exists.
See the script I have attached. It shows the phenomenon : it draws an histogram, wait 5 seconds to let the user have time to open the contextual menu of the histo, then update the histo and if the user click on the contextual menu after the update, it crashes.
How to handle this situation ?
Do I have a way of knowing that the user is interacting with the canvas or its content ?
Any other idea ?
Thanks a lot in advance,
testContext.C (1.54 KB)
Rather than delete ad recreate the histogram object, try reusing it; i.e. where you do ‘delete h1; h1 = new …;’ try ‘h1->Reset();’
Thanks for your reply. The problem is that the histogram is coming from somewhere else… therefore I am just getting a new pointer at each update.
Even in this case you can re-use the existing object.
For example you can do:
h1->Reset(); h1->Add(incoming);if the 2 histograms have the same limits (and name) or you could event try
*h1 = *incoming;.
If it is impossible to re-use the old histogram then to avoid a crash, you would have to replace the ‘delete h1’ by a staging in a list of ‘obsolete’ histogram objects that you would clean up regularly when you somehow are sure the user no longer might be referencing those obsolete histograms.
Thanks for your feedback which helped me identify what the real problem was. In fact, the call to TCanvas::Clear() is guilty. If I remove it, even in the first version of the script where I delete the former histogram, then it works.
Now, just to be sure, if I Draw h1 and then h2 on a canvas without calling Clear() in between, does it create any kind of memory leak ?
Hi again Philippe,
Unfortunately I was a bit fast saying that the problem was fixed.
- When using
It crashes as it did before. Please try it with the script testContext2.C : when the canvas appear click anywhere on the TFrame inside the histo (the background) and wait until the histo get updated but keep the contextual menu opened. Once updated, click on Inspect. Enjoy the crash.
- When using
*h1 = *incoming;
it seems to work with the example testContext3.C that you can use the same way as testContext2.
- This latest way unfortunately crashes when the histogram is updated several time. See testContext4.C for an example : it will update 5 times the histo with 5 seconds of interval. Right click on the background TFrame, wait the update, click Inspect -> it works. Right click again on the background, wait the update, click on Inspect -> it crahes.
What am I doing wrong ?
Thanks for your help,
testContext4.C (1.47 KB)
testContext3.C (1.62 KB)
testContext2.C (1.62 KB)
Philippe, have you had time to have a look at this ?
Do you want me to create a bug in savannah ?
No I did not yet
Feel free to also report this to Savannah, but I will indeed to take a look.
In addition to reusing the Histogram, you need to make sure to also ‘reuse’ the graphics component (TFrame, TAxis, etc.).
This is achieve simply by replace the h1->Draw() after then 1st one, by a call to c1->Modified().
For example in testContext4.C, you should add h1->Draw() before the loop and use
// replace the histo by a new one and display it in the canvas
//*h1 = *h;
c1->Update();inside the loop.
My apologies for the long delay.
testContext4.C (1.5 KB)