3

イベント ハンドラーを保持する変数のアドレスを取得するにはどうすればよいですか?

例えば

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だから私はCPUウィンドウのデータペインで変数を監視したいので、次のように監視できます:

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: TNotifyEvent $253B588
  • FOnChange: 'FOnChange' の検査中にエラーが発生しました: 式エラー
  • Self.FOnChange: 'Self.FOnChange' の検査中にエラーが発生しました: 式エラー
  • @オンチェンジ:@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。2 つの住所です。

4

5 に答える 5

6

アドレスは、DebugInspectorから取得できます。フィールドのアドレスを取得するには、変更が発生する前のある時点で、たとえばコンストラクターを呼び出した直後など、コードにブレークポイントを設定します。次に、デバッグインスペクターでオブジェクトを開きます。古いIDEスタイルでどのように取得するかはわかりませんが、D2010では、[実行]-> [検査...]メニューコマンド、[評価/変更]のボタン、またはキーボードのALT-F5を押すことで取得できます。(ALT-F4を押さないように注意してください!)

Debug Inspectorは、オブジェクトとそのすべてのフィールドを表示します。フィールドの1つをダブルクリックすると、新しいDebugInspectorウィンドウが開きます。編集ボックスの上部にあるようなバーは、フィールドのアドレスになります。これを使用して、値が変更される場所を見つけるためのメモリブレークポイントを設定できます。

于 2010-06-21T17:13:05.727 に答える
4

Delphi 5ではわかりませんが、AExample.FOnChangeにデータブレークポイント(またはアドレスブレークポイント)を設定できるはずです。
値が変わるたびに壊れます。

于 2010-06-21T17:13:57.890 に答える
3

フランソワが提案したスマートな解決策を使用できないので、ハッキングする時が来ました! ブレーキポイントを配置できる場所ならどこでも、次のようなコードを記述します。

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

コンパイラが使用するレジスタは気にしません。最初の MOV 命令に使用されるオフセットである $288 は気にします。これは、「X」アドレスから FOnChange フィールドまでのオフセットです。書き留めておいてください。バグのあるプログラムに戻り、どこかにブレークポイントを設定し、Alt+F5 を押してデバッグ インスペクターを呼び出し (クエリを入力するための空の編集ボックスが表示されない場合は、Ctrl+N を押します)、"Integer( MyExampleVariable)"; 得られた値が何であれ、前のステップで書き留めた数値を合計すると、MyExampleVariable インスタンス用にファイルされた FOnChange のアドレスが得られます。これで、アドレス ブレークポイントを設定できます。

于 2010-06-21T17:33:24.050 に答える
2

それらが Delphi 5 に存在するかどうかはわかりませんが、型TMethodと関数MethodAddressが役立つはずです。

于 2010-06-21T19:03:17.270 に答える
0

なんで?

誰が私の FOnChange ハンドラ変数をジャンクで上書きしているのかを突き止めようとしています。

私はそのビットに答えることができます - あなたはそうです! または、正しく作成されていない間違ったインスタンスを見ていますか? 正しく参照されていませんか?そのようなものになります。Delphi デバッガは、存在しないものを存在するように見せるのが得意です。

少し離れて、木ではなく木を見てみてください。私はあなたがいるところに何度も行ってきましたが、おそらくあなたは間違ったツリーを吠えているでしょう (申し訳ありませんが意図されたしゃれです)。

于 2010-06-21T20:09:07.887 に答える