Delphi:如何获取事件变量的地址?

时间:2010-06-21 16:49:23

标签: delphi debugging delphi-5 disassembly

如何获取持有事件处理程序的变量的地址?

e.g。

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

所以我想在CPU窗口的数据窗格中查看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

替代+ 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 个答案:

答案 0 :(得分:6)

您可以通过Debug Inspector获取地址。要获取字段的地址,请在更改发生之前的某个时刻在代码中放置断点,例如在调用构造函数之后。然后在Debug Inspector中打开您的对象。不确定如何使用旧的IDE样式,但在D2010中,您可以从Run-> Inspect ...菜单命令,Evaluate / Modify中的按钮,或通过键盘上的ALT-F5获取。 (小心你不要打ALT-F4!)

Debug Inspector将向您显示包含其所有字段的对象。双击其中一个字段,它将在新的Debug Inspector窗口中打开。在顶部的编辑框状栏中将是您的字段的地址。您可以使用它来设置内存断点以查找值更改的位置。

答案 1 :(得分:4)

在Delphi 5中不确定但您应该能够在AExample.FOnChange上放置数据断点(或地址断点)。
只要值发生变化,它就会中断。

答案 2 :(得分:3)

由于你不能使用François建议的智能解决方案,现在是时候搞黑了!在任何地方,你可以放一个制动点,写这样的代码:

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字段的OFFSET。记下来。现在回到您的错误程序,在某处设置一个制动点,点击Alt + F5调用Debug Inspector(如果您没有显示空的编辑框以输入查询,则按Ctrl + N)并写入“Integer”( MyExampleVariable)“;无论你得到什么,加上你在上一步记下的数字,你已经获得了为MyExampleVariable实例提交的FOnChange的地址,你现在可以设置一个地址制动点。

答案 3 :(得分:1)

我不知道它们是否存在于Delphi 5中,但类型TMethod和函数MethodAddress应该会有所帮助。

答案 4 :(得分:0)

  

为什么?

     

我正在试图找出谁用垃圾覆盖了我的FOnChange处理程序变量。

我可以回答这个问题 - 你是!或者您正在查看未正确创建的错误实例?没有正确引用?它会是这样的。 Delphi调试器擅长制作一些不存在的东西,直到......

退一步,试着看看木头而不是树木。我已经去过你很多次了,你可能正在吠叫错误的树(对不起双关语)并且不久会给自己打电话给各种各样的名字:)