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

发布于 2024-09-06 15:04:15 字数 2251 浏览 11 评论 0原文

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

例如,

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

except我不知道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:指针$253B588
  • @@OnChange:检查“@@OnChange”时出错:表达式错误
  • @FOnChange@FOnChange:指针 $253B588
  • @@FOnChange: @@FOnChange: ^未键入(无地址) 数据: @@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 的地址,它是两个地址!

How do i get the address of the variable holding an event handler?

e.g.

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

i want the address of the FOnChange private member, event handler, variable.


Why?

i'm trying to figure out who is overwriting my FOnChange handler variable with junk.

i am stepping through code:

if Assigned(FOnChange) then
    FOnChange(Self);

No event handler is ever assigned, and for a while the FOnChange variable is nil in the Watch Window:

@FOnChange: nil
Addr(FOnChange): nil

But later the FOnChange variable is getting turned into junk:

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

So i want to watch the FOnChange variable in data pane of the CPU window, so that i can watch it to from:

00410018 00000000

to

00410018 0000002C

Except i don't know the address of FOnChange; i just made up the $410018.

How can i find the address of an event variable?


Things i've tried

Watch List

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: Error inspecting 'FOnChange': expression error
  • Self.FOnChange: Error inspecting 'Self.FOnChange': expression error
  • @OnChange: @OnChange: Pointer $253B588
  • @@OnChange: Error inspecting '@@OnChange': expression error
  • @FOnChange: @FOnChange: Pointer $253B588
  • @@FOnChange: @@FOnChange: ^Untyped (no address) Data: @@FOnChange $253B588`

The concensus seems to be at address 0x253B588.

Yet when i run some sample code:

MyControl1.OnChange := TheOnChangeHandler;

That turns into:

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

No wonder i can't find an address of FOnChange, it's two addresses!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤君无依 2024-09-13 15:04:15

您可以通过调试检查器获取该地址。要获取字段的地址,请在更改发生之前的某个时刻在代码中放置一个断点,例如在调用构造函数之后。然后在调试检查器中打开您的对象。不知道如何在旧的 IDE 风格中获得它,但在 D2010 中,您可以通过“运行”->“检查...”菜单命令、“评估/修改”中的按钮或通过按键盘上的 ALT-F5 来获得它。 (小心不要按 ALT-F4!)

调试检查器将向您显示对象及其所有字段。双击其中一个字段,它将在新的调试检查器窗口中打开。在顶部类似编辑框的栏中将显示您的字段的地址。您可以使用它来设置内存断点以查找值发生变化的位置。

You can get the address through the Debug Inspector. To get the address of a field, put a breakpoint in your code at some point before the change has happened, for example right after you call the constructor. Then open your object in the Debug Inspector. Not sure how you get it in the old IDE style, but in D2010 you can get this from the Run->Inspect... menu command, from a button in Evaluate/Modify, or by hitting ALT-F5 on the keyboard. (Be careful you don't hit ALT-F4!)

The Debug Inspector will show you your object with all its fields. Double-click on one of the fields and it will open in a new Debug Inspector window. In the edit box-like bar at the top will be the address of your field. You can use this to set a memory breakpoint to find where the value changes.

烟凡古楼 2024-09-13 15:04:15

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

Not sure in Delphi 5 but you should be able to put a Data Breakpoint (or an Address Breakpoint) on your AExample.FOnChange.
It would break whenever the value changes.

小瓶盖 2024-09-13 15:04:15

由于您无法使用 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 字段的偏移量。记下来。现在回到有问题的程序,在某处设置一个制动点,按 Alt+F5 调用调试检查器(如果没有出现空编辑框来输入查询,则按 Ctrl+N)并写入“Integer(我的示例变量)”;无论您得到什么,将您在上一步中记下的数字相加,您就获得了为 MyExampleVariable 实例归档的 FOnChange 地址,现在您可以设置地址制动点。

Since you can't use the smart solution suggested by François, it's time to get hacking! Somewhere, anywhere you can put a brakepoint, write code like this:

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

Put a brakepoint on the X.OnChange := nil line; When the debugger stops there, take a look at the disassembly pane, you'll see something like this:

; 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

You don't care about the registers used by the compiler, you care about the $288, the offset used for the first MOV instruction. That's the OFFSET from the "X" address to the FOnChange field. Note it down. Now go back to your buggy program, set a brakepoint somewhere, hit Alt+F5 to invoke the Debug Inspector (followed by Ctrl+N if you're not presented with an empty edit box to type your query in) and write "Integer(MyExampleVariable)"; Whatever you get, add up the number you noted down at the previous step and you've got the address of the FOnChange filed for the MyExampleVariable instance, you can now set a address brakepoint.

人事已非 2024-09-13 15:04:15

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

I don't know if they exists in Delphi 5, but the type TMethod and the function MethodAddress should be helpful.

狼亦尘 2024-09-13 15:04:15

为什么?

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

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

退后一步,尝试只见木头而不是树。我去过你很多次,你可能找错了树(抱歉,双关语),很快就会给自己起各种各样的名字:)

Why?

i'm trying to figure out who is overwriting my FOnChange handler variable with junk.

I can answer that bit - you are! Or you are looking at the wrong instance that is not created correctly? not referenced correctly? It will be something like that. The Delphi debugger is good at making some thing that does not exist look like it does, until...

Step back a bit, try and see the wood not the trees. I have been where you are many times, you are probably barking up the wrong tree (sorry pun intended) and shortly will call yourself all sorts of names :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文