Monday, January 2, 2006

Why are some object properties zero in the watch window?

This has to do with how the watch window works and the way properties are implemented.

First, the watch window simply provides a view of an area of memory. You can tell it to view the memory in different ways. Because it knows some things about that memory, it can do a limited amount of interpretation: view the contents of character pointers, view the contents of records and so forth.

Second, a bit of explanation as to how properties work. When a component is developed, the component writer declares a property with:
property NameOfProp: TypeOfProp read PropReader write PropWriter;
where:
NameOfProp is the name of the property accessed in the Object Inspector and in code.
TypeOfProp is the type of the property, e.g. Integer, String, TStrings.
PropReader is either a variable of type TypeOfProp or a function with a return type of TypeOfProp.
PropWriter is either a variable of type TypeOfProp or a procedure with a parameter of type TypeOfProp.
Notice the two options for readers and writers. They can be either a variable or a method. Some properties directly access a variable whereas others are the result of code executing. Those properties that fall into the first class can be evaluated without side effects in the watch window, since it looks at memory. Those properties that fall into the second class cannot be evaluated in the watch window without potentially causing side effects.

Because of the possible side effect issue, early versions of Delphi simply did not display the property value. Due to requests to allow this, the debugger was made to optionally show properties which use readers. To see these types of properties, right click on the watch item and select properties. Then check the option to allow function results.

If working in earlier versions of Delphi, where this option is not available, there are several ways to get around the problem:
  1. Create a temporary variable immediately prior to where you want to view a property and assign the property value to the variable. Then put the watch on the temporary variable. You may need to go to the Options page and turn optimizations off.
  2. Put a ShowMessage call in the code where you would normally set the breakpoint and create a message that displays the desired property.
  3. Put a Memo component on the visible form and add a line that displays the desired property where you would normally set the breakpoint.
  4. Set a breakpoint. Right click on the breakpoint in the breakpoint list window and select properties. Show the advanced options. Uncheck Break. In the evaluation section, put in the property name. Now, every time that breakpoint is hit, rather than stopping the debugger, it will write a line to the event log.

No comments: