-3

(Delphi 6 with TChart, Win XP)

I'm getting erratic behavior trying to clear the points from a point series, and of course, this code used to work.

Basically, this part of my program generates 5 data points and plots them. When I try to clear them using OSC_Series.Clear I get a "List index out of bounds [0]" error.

I checked to make sure there was nothing odd about the values I was plotting. All is good there. Then I tried different things to try to isolate and work around the problem.

Here's some code.

type
  TksGraph_DataFrm = class(TForm)
  .
  .
  .
  private
    OSC_Series: TPointSeries
  public
  end;

procedure TksGraph_DataFrm.cat7AnalysisInitialize(var P:TTest_Project);
begin

  // Do a bunch of stuff.

  // Set up the analysis data points series.
  OSC_Series:=TPointSeries.Create(self);
  AnalysisChart.AddSeries(OSC_Series);
  with OSC_Series do
  begin
    Title:='';
    HorizAxis:=aBothHorizAxis;
    VertAxis:=aBothVertAxis;
    SeriesColor:=clRed;
    Pointer.Brush.Color:=clYellow;
    Pointer.HorizSize:=4;
    Pointer.VertSize:=4;
    Pointer.Style:=psRectangle;
    Pointer.Visible:=true;
    LinePen.Color:=clBlack;
    LinePen.Width:=1;
    Linepen.Visible:=true;
    ShowInLegend:=false;
    XValues.Order:=LoNone;
  end;
end;

procedure TksGraph_DataFrm.cat7AnalysisRefresh(var P:TTest_Project);
var X,Y:single;
begin

  X:= some value
  Y:= some value

  // Plot the result.
  OSC_Series.AddXY(X,Y);
  showmessage(
    'Count = '+inttostr(OSC_Series.Count)+#13+
    'X = '+FloatToStr(X)+#13+
    'Y = '+FloatToStr(Y)+#13+
    'Plot-X = '+FloatToStr(OSC_Series.XValue[OSC_Series.Count-1])+#13+
    'Plot-Y = '+FloatToStr(OSC_Series.YValue[OSC_Series.Count-1]));

end;

Here is the routine I to use to reset the series. I'm including code that does and does not work.

procedure TksGraph_DataFrm.cat7AnalysisClear(var P:TTest_Project);
var i:integer;
begin

  // This should work, but it gives me the list out of bounds error
  // unless the count is 0.
  OSC_Series.Clear;

  // This does not work, for obvious reasons. I get a "list out of 
  // bounds [3] for this one.
  for i:=0 to OSC_Series.Count - 1 do OSC_Series.Delete[0];

  // It seems this should work, but again I get the out of bounds [0]  
  // error.
  repeat
    OSC_Series.Delete(0);
  until OSC_Series.Count = 0;

  // This works. Don't ask me why.
  showmessage('A - '+inttostr(OSC_Series.Count));
  OSC_Series.Clear;
  showmessage('B - '+inttostr(OSC_Series.Count));

  // This also works.
  sleep(2000);
  OSC_Series.Clear;

  // This does not work.
  sleep(1000);
  OSC_Series.Clear;

end;

I'm stumped, obviously.

M610
  • 225
  • 1
  • 2
  • 10
  • 2
    Please show a [mcve] or do some debugging – David Heffernan Mar 16 '16 at 05:56
  • Do you use single thread? Can you be sure that OSC_Series is manipulated from same thread? – Zamrony P. Juhara Mar 16 '16 at 07:05
  • Are you using the TeeChart Standard version shipped with Delphi 6? I can't reproduce the problems with the latest version, v2015.16 in RAD XE. In my test application I just placed a TChart and a TButton on a new form. I created the `OSC_Series` at `OnCreate` and I call the code from your `cat7AnalysisClear` in my `Button1Click`. I'm also calling `OSC_Series.FillSampleValues();` before each "clear attempt" to check it (I'm not using your `cat7AnalysisRefresh`) – Yeray Mar 16 '16 at 09:03
  • A thread is not involved here. – M610 Mar 16 '16 at 17:29
  • Series.Clear works everywhere else, so it is unlikely to be a problem in TeeChart. I renamed the series to OCS_SeriesA, and that didn't help. I referenced it a Self.OSC_Series, no change. I think the question of confusing the name of the series with another is settled. I tried placing the code in a try... except block and EurekaLog grabs it before my code does. The repeat..until code works only if I have a ShowMessage line between the Series.Delete(0) and while statements. The ShowMessage line is trying to tell me something. – M610 Mar 16 '16 at 17:36
  • I can post the whole section of code involved if that helps. (The whole thing is over 9000 lines.) – M610 Mar 16 '16 at 17:37

2 Answers2

1

This smells like the code is working with an object (OSC_Series) which has been destroyed and the memory then re-used for something else. When you then use the stale reference to that memory you get unexpected and unpredictable results.

Where is OSC_Series free'd ?

I would check all such places and make sure that you do not attempt to use the OSC_Series reference after it has been free'd.

Note also that since the series is owned by the form it could be that the form itself is contriving to executing code in events after it has destroyed its owned components (including this series).

Deltics
  • 22,162
  • 2
  • 42
  • 70
  • Thanks. I checked for that. This variable is local to this form and in another form. A global search does not show it being referenced anywhere else. OSC_Series is freed when the form closes. (I have memory leak detection turned on in EurekaLog.) The only time I've had problems like this was when I had range checking turned off and I was overwriting memory. – M610 Mar 16 '16 at 05:44
1

OK, dumb and not dumb.

I experimented with where I put the showmessage statement. I found I could only avoid the error if that statement came after the OSC_Series.Clear statement. I kept moving that statement back until it was after the call to the AnalysisRefresh routine, which is in a button's OnClick event handler. This means that none of the code in the refresh, enable, or update routines was causing this.

Stepping back a bit, if the AnalysisRefresh routine fails the user is shown a message. After that box is closed OSC_Series.Clear is called. If I close the box by pressing SPACE or ENTER on the keyboard... no error. If I use the mouse, error.

The chart behind the mouse has an OnMouseMove event where I display the mouse position on a status bar. I also display a hint if the mouse is near a plotted point. After clicking the message box with a mouse to close it the OnMouseMove event is called and by the time it gets to where it can display the hint, the plotted point is gone, and... error.

So, it seemed like an almost random error, but it wasn't. The trigger was just somewhere else entirely. That's you my try/except block wasn't catching the error. EurekaLog was catching it, but in a different procedure far, far away. (Deltics' answer was pretty close.)

Thanks for your help and suggestions.

Dang it if some days I can push hundreds of lines of code with no problems, then something like this pops up and it costs me near two days.

M610
  • 225
  • 1
  • 2
  • 10
  • This feels like a "Dear Diary" entry. Nothing you talk about here relates to details in the question. You should not have asked the question until you had a clear problem statement. You should have just debugged your program. Which you did. An as soon as you isolated the problem the answer was obvious. – David Heffernan Mar 16 '16 at 21:39
  • So, not cryptic enough? I figured describing how I found the problem would be at least as helpful as describing what I found. I had worked on this for over a day and was stumped. Everything pointed to a problems in clearing the series. I search here and elsewhere for similar problems. Finding nothing, I posted here, but I didn't give up. The problem turned out to be similar to what Deltic was saying, that other code was trying to use the series. – M610 Mar 17 '16 at 00:17
  • No. The exact opposite. The question is too vague as can be seen by an answer that talks about things not in the question. – David Heffernan Mar 17 '16 at 06:59
  • "Basically, this part of my program generates 5 data points and plots them. When I try to clear them using OSC_Series.Clear I get a "List index out of bounds [0]" error." I followed this with code examples showing what I did to isolate the problem down to one line of code, then how doing seemingly unrelated things (showmessage and sleep) seemed to eliminate the problem. It made no sense. I was stumped. I asked if anyone had seen something similar. – M610 Mar 17 '16 at 17:43
  • Yes. And I'm telling you that does not make a good question here. I don't expect you to agree with me. – David Heffernan Mar 17 '16 at 17:44