Question

Voici un code que j'ai:

MyClass* MyClass::getInstance()
{
   static MyClass instance;
   return &instance;
}

Je veux examiner les valeurs actuelles de ce singleton. Mais je suis actuellement arrêté trois heures avant l'exécution, et la raison pour laquelle je suis en pause est que je n'ai plus de mémoire. Donc, je ne peux pas mettre un point d'arrêt dans cette méthode pour voir quelle est la valeur.

Ma question est donc de savoir comment faire référence à cette variable instance à partir d'une portée globale. J'ai essayé de s'y référer en tant que MyClass :: getInstance :: instance mais cela ne fonctionne pas. Je suppose que getInstance doit être décoré d’une manière ou d’une autre. Quelqu'un sait comment?

Ceci est dans Visual Studio 2008.

Était-ce utile?

La solution

La variable statique instance , dont la portée est fonction, n'apparaît pas dans un fichier .map généré par cl.exe / Fm . , et cela ne s'affiche pas lorsque j'utilise x nom_programme! * MyClass * dans WinDbg, de sorte que le nom mutilé ne semble pas contenir du tout MyClass .

Option 1: désassemblez MyClass :: getInstance

Cette approche semble plus facile:

0:000> uf programname!MyClass::getInstance
programname!MyClass::getInstance [programname.cpp @ 14]:
   14 00401050 55              push    ebp
   14 00401051 8bec            mov     ebp,esp
   15 00401053 a160b34200      mov     eax,dword ptr [programname!$S1 (0042b360)]
   15 00401058 83e001          and     eax,1
   15 0040105b 7526            jne     funcstat!MyClass::getInstance+0x33 (00401083)

programname!MyClass::getInstance+0xd [programname.cpp @ 15]:
   15 0040105d 8b0d60b34200    mov     ecx,dword ptr [programname!$S1 (0042b360)]
   15 00401063 83c901          or      ecx,1
   15 00401066 890d60b34200    mov     dword ptr [programname!$S1 (0042b360)],ecx
   15 0040106c b9b0be4200      mov     ecx,offset programname!instance (0042beb0)
   15 00401071 e88fffffff      call    programname!ILT+0(??0MyClassQAEXZ) (00401005)
   15 00401076 68e03e4200      push    offset programname!`MyClass::getInstance'::`2'::`dynamic atexit destructor for 'instance'' (00423ee0)
   15 0040107b e8f3010000      call    programname!atexit (00401273)
   15 00401080 83c404          add     esp,4

programname!MyClass::getInstance+0x33 [programname.cpp @ 16]:
   16 00401083 b8b0be4200      mov     eax,offset programname!instance (0042beb0)
   17 00401088 5d              pop     ebp
   17 00401089 c3              ret

À partir de cela, nous pouvons dire que le compilateur a appelé l'objet $ S1 . Bien entendu, ce nom dépendra du nombre de variables statiques à portée de fonction de votre programme.

Option 2: rechercher dans la mémoire l'objet

Pour approfondir la suggestion de @ gbjbaanb, si MyClass a des fonctions virtuelles, vous pourrez peut-être trouver son emplacement de la manière la plus difficile qui soit:

  • Effectuez une sauvegarde complète de la mémoire du processus.
  • Chargez le vidage de la mémoire complète dans WinDbg.
  • Utilisez la commande x pour trouver l'adresse de la table vtable de MyClass:
    0:000> x programname!MyClass::`vftable'
    00425c64 programname!MyClass::`vftable' = 
  • Utilisez la commande s pour rechercher dans l'espace d'adressage virtuel du processus (dans cet exemple, 0 à 2 Go) des pointeurs vers la table vtable de MyClass:
    0:000> s -d 0 L?7fffffff 00425c64
    004010dc  00425c64 c35de58b cccccccc cccccccc  d\B...].........
    0040113c  00425c64 8bfc458b ccc35de5 cccccccc  d\B..E...]......
    0042b360  00425c64 00000000 00000000 00000000  d\B.............
  • Utilisez la commande dt pour rechercher le décalage vtable de la classe et soustrayez-le des adresses renvoyées par la recherche. Ce sont des adresses possibles pour l'objet.
    0:000> dt programname!MyClass
       +0x000 __VFN_table      : Ptr32 
       +0x008 x                : Int4B
       +0x010 y                : Float
  • Utilisez dt nom_programme! MyClass 0042b360 pour examiner les variables membres de l’objet, en testant l’hypothèse selon laquelle l’objet est situé en 0042b360 (ou une autre adresse). Vous obtiendrez probablement des faux positifs, comme je l’ai déjà mentionné, mais en inspectant les variables membres, vous pourrez peut-être déterminer laquelle est votre singleton.

C’est une technique générale pour rechercher des objets C ++. C’est une sorte de surcharge lorsque vous pouvez simplement désassembler MyClass :: getInstance .

Autres conseils

Dans gdb, vous pouvez placer un point de contrôle sur le nom mutilé de la variable.

Par exemple, avec cette fonction:

int f() {
    static int xyz = 0;
    ++xyz;

    return xyz;
}

Je peux regarder _ZZ1fvE3xyz (comme mutilé par gcc 3.2.3 ou gcc 4.0.1).

Ce code a l'air dangereux ...: -)

Quoi qu'il en soit, votre nom mutilé dépendra de votre Convention d'appel Ainsi, avant de trouver votre nom mangle, vous devez savoir ce que votre environnement de génération utilise comme convention d'appel. MSDN contient beaucoup plus d’informations sur la convention d’appel.

En outre, une façon de connaître toutes ces informations sur votre classe consiste à inspecter votre VTable, qui se trouve dans les 4 premiers octets de votre objet. Un astuce astucieuse utilisée par les inverseurs est un indicateur VC ++ caché reportSingleClassLayout qui affiche la structure de classe de manière artistique ASCII.

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