Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi - How do I break when a form's ComponentCount decrements

The code below is reproduced from Toolbar2000. It is part of routine that reads toolbar positions and dock states from an INI file. I call this routine during initialisation. This code below is iterating through all the components on the main form (OwnerComponent) and loading the settings of any toolbars it finds.

for I := 0 to OwnerComponent.ComponentCount-1 do begin
  ToolWindow := OwnerComponent.Components[I];  //  <------------------------
....

This iterating takes some time (seconds - there are 1500-odd components on the form) and I'm getting a range error at the point shown. I have ascertained that one or more items is being shed from the main form's components while this loop is executing, so eventually the loop tries to access one past the end of the array once this has happened (presumably it would be better to code this as a "downto" for-loop to prevent this).

Anyway, I need to find out where the main form is losing a component. Can anybody give me any Delphi 2006 debugging tips on how to do this? I wouldn't expect any main form components to be freed at this point in my program.

UPDATE

I found that when I had repositioned a toolbar's default dock position at design-time I had inadvertently docked it onto another toolbar, rather than the dock site that the other toolbar was in. I fixed the problem by removing the toolbar from the toolbar it was docked in and adding it to the dock instead. So the arrangement that caused the problem was:

Dock 
  Toolbar 1
    Control 1
    Control 2
    Toolbar 2
      Control 3
      Control 4

and the fix was to arrange them thus:

Dock 
  Toolbar 1
    Control 1
    Control 2
  Toolbar 2
    Control 3
    Control 4

It still points to a bug in the TB2k code though - one would assume it should be able to handle nested toolbars.

like image 230
rossmcm Avatar asked Jan 19 '23 21:01

rossmcm


2 Answers

In addition to Lieven's answer, you could also use debug dcu's and set a breakpoint in TComponent.Destroy just before you enter the loop.

In both cases you will need to examine the call stack to see where the call/change to count is coming from.

A very interesting article on breakpoints was written by Cary Jensen: http://caryjensen.blogspot.com/2010/08/breakpoints-with-side-effects.html

like image 72
Marjan Venema Avatar answered Feb 05 '23 17:02

Marjan Venema


You'll have to add a data breakpoint at @Self.FComponents.FCount to break whenever the count changes.

  • ComponentCount is a property that returns the value from GetComponentCount
  • GetComponentCount returns FComponents.Count.
  • FComponents is a TList instance that has a private FCount variable.
like image 33
Lieven Keersmaekers Avatar answered Feb 05 '23 16:02

Lieven Keersmaekers