Question

Comment puis-je obtenir l'adresse de la variable qui contient un gestionnaire d'événements?

par exemple.

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

Je veux que le adresse de l'organe privé FOnChange, gestionnaire d'événements, variable.


Pourquoi?

J'essaie de savoir qui est ma variable écrasant gestionnaire de FOnChange avec l'ordure.

Je suis pas à pas dans le code:

if Assigned(FOnChange) then
    FOnChange(Self);

est jamais attribué Aucun gestionnaire d'événements, et pour un moment la variable FOnChange est nil dans la fenêtre Espion:

@FOnChange: nil
Addr(FOnChange): nil

Mais plus tard, la variable est FOnChange se transforme en ordure:

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

Alors je veux regarder la variable FOnChange dans le volet de données de la fenêtre CPU, afin que je puisse le regarder à partir de:

00410018 00000000

à

00410018 0000002C

Sauf que je ne sais pas savoir l'adresse de FOnChange; Je viens de faire le $410018.

Comment puis-je trouver les adresse d'une variable d'événement?


Ce que j'ai essayé

Liste Regarder

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: Erreur d'inspection 'FOnChange': erreur d'expression
  • Self.FOnChange: Erreur d'inspection 'Self.FOnChange': erreur d'expression
  • @OnChange : @OnChange: Pointer $253B588
  • @@ OnChange : Erreur inspectant '@@ OnChange': Erreur d'expression
  • @FOnChange : @FOnChange: Pointer $253B588
  • @@ FOnChange : @@FOnChange: ^Untyped (no address) Données: @@ FOnChange $ 253B588`

Le concensus semble être à l'adresse 0x253B588.

Pourtant, quand je lance un code exemple:

MyControl1.OnChange := TheOnChangeHandler;

qui se transforme en:

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

Pas étonnant que je ne peux pas trouver une adresse de FOnChange, il est deux adresses!

Était-ce utile?

La solution

Vous pouvez obtenir l'adresse par l'inspecteur de débogage. Pour obtenir l'adresse d'un champ, mettre un point d'arrêt dans votre code à un moment donné avant que le changement est arrivé, par exemple juste après que vous appelez le constructeur. Ensuite, ouvrez votre objet dans l'inspecteur de débogage. Je ne sais pas comment vous l'obtenez dans le style ancien IDE, mais D2010 vous pouvez obtenir auprès de l'run-> Vérifier ... commande de menu, à partir d'un bouton Evaluer / Modifier ou en appuyant sur ALT-F5 sur le clavier. (Attention, vous ne touchez ALT-F4!)

L'inspecteur de débogage vous montrer votre objet avec tous ses champs. Double-cliquez sur l'un des champs et il ouvrira dans une nouvelle fenêtre Inspecteur de débogage. Dans la barre boîte édition en haut sera l'adresse de votre champ. Vous pouvez l'utiliser pour définir un point d'arrêt de mémoire pour trouver où les changements de valeur.

Autres conseils

Je ne sais pas dans Delphi 5 mais vous devriez être en mesure de mettre un point d'arrêt de données (ou un point d'arrêt adresse) sur votre AExample.FOnChange.
Il se briserait chaque fois que la valeur change.

Puisque vous ne pouvez pas utiliser la solution intelligente proposée par François, il est temps de piratage! Quelque part, partout où vous pouvez mettre un brakepoint, écrire du code comme ceci:

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

Mettez un brakepoint sur la X.OnChange: = ligne nulle; Lorsque le débogueur arrête là, jetez un oeil à la fenêtre de démontage, vous verrez quelque chose comme ceci:

; 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

Vous ne vous inquiétez pas sur les registres utilisés par le compilateur, vous vous souciez de 288 $, le décalage utilisé pour la première instruction MOV. Ce sont les OFFSET de l'adresse « X » au champ FOnChange. Notez-le. Maintenant, retournez à votre programme bogué, définir un endroit de brakepoint, appuyez sur Alt + F5 pour appeler l'inspecteur de débogage (suivi par Ctrl + N si vous n'êtes pas présenté avec une zone d'édition vide pour saisir votre requête dans) et de l'écriture « Entier ( MyExampleVariable) "; Tout ce que vous obtenez, ajoutez le numéro que vous avez noté à l'étape précédente et que vous avez l'adresse du FOnChange déposé pour l'instance MyExampleVariable, vous pouvez maintenant définir une brakepoint d'adresse.

Je ne sais pas si elles existent dans Delphi 5, mais le type TMethod et la fonction MethodAddress devrait être utile.

  

Pourquoi?

     

J'essaie de savoir qui est ma variable écrasant gestionnaire de FOnChange avec l'ordure.

Je peux répondre peu - vous! Ou vous êtes à la recherche au mauvais exemple qui n'est pas créé correctement? non référencé correctement? Ce sera quelque chose comme ça. Le débogueur Delphi est bon à faire quelque chose qui n'existe pas l'air comme il le fait, jusqu'à ce que ...

Reculer un peu, essayer et voir le bois non les arbres. Je suis où vous êtes plusieurs fois, vous êtes probablement aboyer le mauvais arbre (jeu de mots désolé intended) et va bientôt vous appeler toutes sortes de noms:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top