如何获取持有事件处理程序的变量的地址?
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: TNotifyEvent $253B588
@OnChange: Pointer $253B588
@FOnChange: Pointer $253B588
@@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
的地址,这是两个地址!
答案 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调试器擅长制作一些不存在的东西,直到......
退一步,试着看看木头而不是树木。我已经去过你很多次了,你可能正在吠叫错误的树(对不起双关语)并且不久会给自己打电话给各种各样的名字:)