Почему некоторые свойства выходят за рамки списка наблюдения, а другие нет? - PullRequest
5 голосов
/ 23 августа 2011

Прежде всего, извините за пример длинного кода, но я считаю, что это необходимо для иллюстрации моей проблемы.

В качестве помощи при отладке я часто представляю метод "DebugString" для своих объектов, который возвращаеткраткое описание объекта.Но иногда мои объекты слишком сложны, чтобы оптимально представлять их в одной строке, поэтому я использую списки строк.Теперь я хотел бы использовать отличные визуализаторы отладки в Delphi для мониторинга моего объекта.Я делаю это, чтобы ввести свойство с помощью метода get, который перестраивает список строк.

Это работает, но для каждой трассируемой строки свойство выходит за рамки видимости, поэтому я должен щелкнуть увеличительное стекло.в окне просмотра еще раз, чтобы увидеть значение.Почему это?

Для воспроизведения создайте новое консольное приложение:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes;

type
  TMyClass = class
  private
    FInternalData : array[0..4] of integer;
    FDebugStringList : TStringList;
    procedure RebuildDebugStringlist;
    function GetDebugStringList: TStringList;
    function GetDebugString : string;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Scramble;
    property DebugStringList : TStringList read GetDebugStringList;
    property DebugString : string read GetDebugString;
  end;

constructor TMyClass.Create;
begin
  FDebugStringList := TStringList.Create;
end;

destructor TMyClass.Destroy;
begin
  FDebugStringList.Free;
  inherited;
end;

function TMyClass.GetDebugString: string;
var
  I : integer;
begin
  Result := 'Object state: ';
  for I := 0 to 3 do
    Result := Result + inttostr(FInternalData[I])+' ';
end;

function TMyClass.GetDebugStringList: TStringList;
begin
  RebuildDebugStringlist;
  Result := FDebugStringlist;
end;

procedure TMyClass.RebuildDebugStringlist;
var
  I : integer;
begin
  FDebugStringList.Clear;

  FDebugStringList.Add('Object state:');
  for I := 0 to 4 do
    FDebugStringList.Add(inttostr(FInternalData[I]));
end;

procedure TMyClass.Scramble;
var
  I : integer;
begin
  for I := 0 to 4 do
    FInternalData[I] := Random(100);
end;

var
  vMyObj : TMyClass;

begin
  vMyObj := TMyClass.Create;
  try
    vMyObj.Scramble;
    vMyObj.Scramble;
    vMyObj.Scramble;
  finally
    vMyObj.Free;
  end;

  readln;
end.
  1. Добавьте часы для "vMyObj.DebugStringList" и "vMyObj.DebugString"
  2. Поместите точку остановав строке 77 (2-й «vMyObj.Scramble») и запустите.
  3. Нажмите на лупу рядом с часами «DebugStringList», чтобы получить визуализатор
  4. Обратите внимание, что визуализатор работает хорошо:)
  5. Перейдите на следующую строку.Визуализатор теперь показывает, что часы находятся вне поля зрения.
  6. Нажмите лупу еще раз, чтобы увидеть новое состояние объекта.

Почему визуализатор говорит, что часы находятся вне поля зрения?Как я могу это исправить?

PS: я знаю, что могу писать отладочные визуализаторы, но я использую "DebugString" и "DebugStringList" в некоторых автоматических тестах, и я действительно хотел бы использовать их таким простым способом.

Обновление: я использую Delphi XE

Обновление 2: Несмотря на все усилия Marjan Venema, у меня до сих пор нет решения этой проблемы.Я подал отчет в Embarcadero (КК № 98062, пожалуйста, проголосуйте :-)).Тем не менее, я подозреваю, что Embarcadero потребуется время, чтобы решить эту проблему, и, видя, как я все еще заинтересован в обходном пути, я предложу небольшую награду.Никогда раньше не пробовал, поэтому будет интересно посмотреть, что получится: -)

Ответы [ 3 ]

4 голосов
/ 23 августа 2011

Это выходит за рамки, потому что это именно то, что происходит, когда выполняется Scramble. Возможно, ошибка в том, что визуализатор не обновляется, когда возвращается в область видимости. Еще не смотрели визуализатор TStrings, но обходной путь - использовать нетипизированную переменную-указатель для FDebugStringList и поместить наблюдение за тип-передачей этого TStringList к этому разыменованному указателю.

var
  vMyObj : TMyClass;
  vSL: Pointer;

{$OPTIMIZATION OFF}
begin
  vMyObj := TMyClass.Create;
  try
    vSL := @(vMyObj.FDebugStringList);

и часы на:

TStringList(vSL^)

Когда вы сейчас прерветесь на второй схватке, откройте визуализатор для vSL, вы увидите содержимое FDebugStringList. Когда вы переступаете через эту вторую схватку, вы видите, что визуализатор «думает, пока идет схватка, а затем обновляется, возвращаясь к основному уровню».

Подводный камень : вам нужно убедиться, что нетипизированная переменная-указатель не будет оптимизирована. Так что либо используйте его нетривиально, убедитесь, что оптимизация отключена во время отладки.

Редактировать: К сожалению, кажется, что обходной путь показывает устаревшие значения. См. Комментарий Свейна.

Обновление

Отказ от ответственности: я не эксперт по ToolsAPI. Беглый осмотр модулей StringListVisualizer и ToolsAPI показывает, что RefreshVisualizer "{вызывается, когда необходимо обновить данные для визуализатора}". Кроме того, строка «RefreshVisualizer» находится только в объявлении интерфейса в модуле ToolsAPI и объявляется и реализуется в модуле StringListVisualizer. Таким образом, на данный момент я предполагаю, что отладчик должен вызывать RefreshVisualizer при возврате для остановки при третьем вызове Scramble, но этого не происходит. Стоит отчет о КК на мой взгляд. По крайней мере, это «Недостаток взаимодействия с пользователем».

1 голос
/ 31 августа 2011

Согласно Являются ли строки Delphi неизменяемыми? , строки Delphi копируются при записи - поэтому, когда вы изменяете FDebugStringList внутри процедуры RebuildDebugStringlist, она, вероятно, выбрасывает старую строку, заставляя ее идти выходит за рамки.

Можете ли вы попытаться изменить строку напрямую (используя арифметику указателей и т. Д.), Чтобы повторно использовать ту же копию, и посмотреть, работает ли она? Конечно, это предполагает, что вы заранее знаете максимальную длину вывода отладки и можете соответственно установить начальную длину строки.

1 голос
/ 27 августа 2011

Может быть, визуализатор не очень хорошо работает с выключенными стековыми фреймами, а функции короткого геттера не имеют стековых фреймов?

Посмотрите, помогает ли отключение оптимизации и включение кадров стека, и добавьте результат в свой КК.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...