16

As an example, given the code extract below, I would like to define a breakpoint that triggers whenever the object field value changes and optionally, breaks on a condition (False or True in this case).

type
  TForm1 = class(TForm)
    EnableButton: TButton;
    DisableButton: TButton;
    procedure EnableButtonClick(Sender: TObject);
    procedure DisableButtonClick(Sender: TObject);
  private
    FValue: Boolean; // <== Would like to define a breakpoint here whenever FValue changes.
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DisableButtonClick(Sender: TObject);
begin
  FValue := False;
end;

procedure TForm1.EnableButtonClick(Sender: TObject);
begin
  FValue := True;
end;
Sae1962
  • 1,122
  • 15
  • 31
Jack G.
  • 3,681
  • 4
  • 20
  • 24
  • PS - You cannot place a breakpoint inside of a class (interface), breakpoints must be in the implementation. – Jerry Dodge Jan 04 '13 at 21:05
  • No. This breakpoint is defined in the interface section. How could it be defined in the implementation? It's a data breakpoint. – Jack G. Jan 04 '13 at 21:12
  • Then I must not understand, First of all I don't know what specifically a "data breakpoint" is, and second of all you never mentioned that term in your question. You just said "breakpoint". – Jerry Dodge Jan 04 '13 at 22:34
  • 1
    Please don't add answers to your question. If you want to add answers, do so in an answer. – David Heffernan Jan 04 '13 at 22:45
  • @Jerry - A data breakpoint is hit when data having the specified length at the specified address changes. I don't think it would be correct to talk about the line number where a data breakpoint corresponds with the source. – Sertac Akyuz Jan 04 '13 at 22:52
  • Make a 'FValue' boolean property with breakpoints on the setter/getter methods? – Martin James Jan 05 '13 at 20:15
  • @Martin except that in my real case scenario the field is a visual component publicly accessible all over the place. Therefore the need to breakpoint when the value changes. – Jack G. Jan 05 '13 at 20:19

2 Answers2

28

Run the application under the debugger,

select 'Run' from the IDE menu then select 'Add Breakpoint' at the very bottom, then 'Data Breakpoint...'.

enter 'Form1.FValue' as input to the 'Adress:' field. You can also set your condition in the same dialog.

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • @Jerry: Except when it doesn't. Conditional breakpoints take a few task-switches, requiring several milliseconds to evaluate, and if whatever you're testing is in a tight loop, that can add up quickly. I've used your solution before when the overhead of conditional breakpoints causes program execution to bog down. (You just have to remember to take it back out again when you're done!) – Mason Wheeler Jan 04 '13 at 23:25
  • @Mason - In my experience, that's especially correct with the 64bit debugger (XE2), I try to avoid conditional breaking in 64bit. I feel something is wrong with the 64bit debugger, not just a few task switches. – Sertac Akyuz Jan 04 '13 at 23:49
3

Some additional information thanks to Sertac answer and comment from David.

One can define a breakpoint based on changes in an array item with a condition.

In this case the data breakpoint is defined as follow:

Form1.FBooleans[0] = True

Code extract:

type
  TBooleanArray = array of Boolean;

  TForm1 = class(TForm)
    EnableButton: TButton;
    DisableButton: TButton;
    procedure EnableButtonClick(Sender: TObject);
    procedure DisableButtonClick(Sender: TObject);
  private
    FBooleans: TBooleanArray; // Breakpoint defined here with the condition
  public
    constructor Create(AOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TForm1.Create(AOwner: TComponent);
var
  AIndex: Integer;
begin
  inherited;
  SetLength(FBooleans, 3);
  for AIndex := 0 to Length(FBooleans) - 1 do
  begin
    FBooleans[AIndex] := (AIndex mod 2) = 1;
  end;
end;

procedure TForm1.DisableButtonClick(Sender: TObject);
begin
  FBooleans[0] := False;
end;

procedure TForm1.EnableButtonClick(Sender: TObject);
begin
  FBooleans[0] := True; // Beakpoint stops here on condition.
end;
Jack G.
  • 3,681
  • 4
  • 20
  • 24