Delphi: Как получить адрес переменной события? - PullRequest
3 голосов
/ 21 июня 2010

Как получить адрес переменной, содержащей обработчик события?

, например

TExample = class(TObject)
private
    FOnChange: TNotifyEvent;
end;

я хочу адрес FOnChange частного члена, обработчик событий, переменную.


Почему?

Я пытаюсь выяснить, кто перезаписывает мою переменную FOnChange с помощью мусора.

Я прошёл код:

if Assigned(FOnChange) then
    FOnChange(Self);

Обработчик событий никогда не назначается, и для некоторое время переменная FOnChange равна nil в окне просмотра:

@FOnChange: nil
Addr(FOnChange): nil

Но позже переменная FOnChange превращается в мусор:

@FOnChange: $2C
Addr(FOnChange): $2C

Итак, я хочу посмотреть переменную FOnChange в области данных окна ЦП, чтобы я мог просматривать ее с:

00410018 00000000

до

00410018 0000002C

За исключением того, что я не знаю адрес FOnChange; я только что составил $410018.

Как мне найти адрес переменной события?


Вещи, которые я пробовал

Список наблюдения

OnChange: nil
@OnChange: nil
@@OnChange: Variable required
@FOnChange: nil
Assigned(OnChange): False
Assigned(FOnChange): False
@@FOnChange: $253B588
addr(addr(FOnChange)): $253B588

Alt + F5

  • OnChange: OnChange: TNotifyEvent $253B588
  • FOnChange: Ошибка проверки 'FOnChange': ошибка выражения
  • Self.FOnChange: Ошибка проверки Self.FOnChange: ошибка выражения
  • @ OnChange : @OnChange: Pointer $253B588
  • @@ OnChange : Ошибка проверки '@@ OnChange': ошибка выражения
  • @ FOnChange : @FOnChange: Pointer $253B588
  • @@ FOnChange : @@FOnChange: ^Untyped (no address) Данные: @@ FOnChange $ 253B588`

Консенсус, кажется, находится по адресу 0x253B588.

Тем не менее, когда я запускаю пример кода:

MyControl1.OnChange := TheOnChangeHandler;

Это превращается в:

mov edx,[ebp+$08]         ;move stack variable $08 into edx
mov [eax+$00000208],edx   ;and then into offset $208 of my control

mov edx,[ebp+$0c]         ;move stack variable $0c into edx
mov [eax+$0000020c],edx   ;and then into offset $20c of my control

Не удивительно, что я не могу найти адрес FOnChange, это два адреса!

Ответы [ 5 ]

6 голосов
/ 21 июня 2010

Вы можете получить адрес через инспектора отладки. Чтобы получить адрес поля, поместите точку останова в свой код в некоторый момент до того, как произойдет изменение, например, сразу после вызова конструктора. Затем откройте ваш объект в Инспекторе отладки. Не уверен, как вы получаете его в старом стиле IDE, но в D2010 вы можете получить это из команды меню Run-> Inspect ..., с помощью кнопки в Evaluate / Modify или нажав ALT-F5 на клавиатуре. (Будьте осторожны, не нажимайте ALT-F4!)

Инспектор отладки покажет вам ваш объект со всеми его полями. Дважды щелкните по одному из полей, и оно откроется в новом окне Инспектора отладки. В поле редактирования в виде поля вверху будет адрес вашего поля. Вы можете использовать это, чтобы установить точку останова памяти, чтобы найти, где значение изменяется.

4 голосов
/ 21 июня 2010

Не уверен в Delphi 5, но вы должны иметь возможность поставить точку останова данных (или точку останова адреса) на свой AExample.FOnChange. Он будет прерываться при изменении значения.

3 голосов
/ 21 июня 2010

Поскольку вы не можете использовать умное решение, предложенное Франсуа, пришло время взломать!Где-нибудь, где бы вы ни ставили точку торможения, напишите код, подобный следующему:

var X:TExample;
X.OnChange := nil;

Поместите точку торможения на линию X.OnChange: = nil;Когда отладчик останавливается на этом, взгляните на панель разборки, вы увидите что-то вроде этого:

; assembler blah blah to get the address of X
xor EDX ; or whatever the compiler finds appropriate this time of day
mov [eax + $00000288], edx
mov [eax + $0000028c], edx

Вам не нужны регистры, используемые компилятором, вы заботитесь о $ 288,смещение, используемое для первой инструкции MOV.Это смещение от адреса «X» до поля FOnChange.Запишите это.Теперь вернитесь к своей глючной программе, где-то установите точку торможения, нажмите Alt + F5, чтобы вызвать Инспектор отладки (затем Ctrl + N, если у вас нет пустого поля ввода для ввода запроса), и напишите «Integer (MyExampleVariable) ";Что бы вы ни получили, сложите число, которое вы записали на предыдущем шаге, и вы получите адрес FOnChange, зарегистрированный для экземпляра MyExampleVariable, теперь вы можете установить адресную точку торможения.

1 голос
/ 21 июня 2010

Я не знаю, существуют ли они в Delphi 5, но тип TMethod и функция MethodAddress должны быть полезны.

0 голосов
/ 22 июня 2010

Почему?

Я пытаюсь выяснить, кто перезаписывает мою переменную обработчика FOnChange мусором.

Я могу ответить на этот бит - вы! Или вы смотрите на неправильный экземпляр, который создан неправильно? ссылки не правильно? Это будет что-то подобное. Отладчик Delphi хорош в том, что некоторые вещи, которые не существуют, выглядят так же, как и до ...

Сделай шаг назад, попробуй и посмотри на дерево, а не на деревья. Я был там, где вы были много раз, вы, вероятно, лаете не на то дерево (простите за каламбур) и вскоре назовете себя разными именами

...