c++ - una - variables locales pdf
¿Cómo destruye VC++ los nombres de variables estáticas locales? (3)
Aquí hay un código que tengo:
MyClass* MyClass::getInstance()
{
static MyClass instance;
return &instance;
}
Quiero ver los valores actuales de este singleton. Pero actualmente estoy pausado tres horas en la ejecución, y la razón por la que estoy en pausa es que me he quedado sin memoria. Así que no puedo poner un punto de interrupción en este método allí para ver cuál es el valor.
Mi pregunta es cómo referirme a esta variable de instance
desde un alcance global. Intenté referirme a él como MyClass::getInstance::instance
pero eso no funciona. Supongo que getInstance
tiene que ser decorado de alguna manera. Alguien sabe como?
Esto es en Visual Studio 2008.
En gdb, puedes poner un punto de observación sobre el nombre destrozado de la variable.
Por ejemplo, con esta función:
int f() {
static int xyz = 0;
++xyz;
return xyz;
}
Puedo ver _ZZ1fvE3xyz (como destrozado por gcc 3.2.3 o gcc 4.0.1).
Ese código solo parece peligroso ... :-)
Pero de todos modos, su nombre destruido dependerá de su Convención de Llamadas. Entonces, antes de encontrar su nombre de grupo, necesita saber qué es lo que usa su entorno de compilación como convención de llamadas. MSDN tiene mucha más información sobre convenciones de llamadas.
Además de esto, una forma de averiguar toda esta información sobre su clase es inspeccionar su VTable, que se encuentra en los primeros 4 bytes de su objeto. Un ingenioso truco que utilizan los inversores es un indicador de VC ++ oculto reportSingleClassLayout que imprime la estructura de clase de manera ASCII art.
Bueno, la variable de instance
estática con ámbito de función no aparece en un archivo .map
generado por cl.exe /Fm
, y no aparece cuando utilizo x programname!*MyClass*
en WinDbg, por lo que el nombre mutilado no parece contener MyClass
en absoluto.
Opción 1: Desmontar MyClass::getInstance
Este enfoque parece más fácil:
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
De esto podemos decir que el compilador llamó al objeto $S1
. Por supuesto, este nombre dependerá de la cantidad de variables estáticas con función de función que tenga su programa.
Opción 2: memoria de búsqueda para el objeto
Para ampliar la sugerencia de @ gbjbaanb, si MyClass
tiene funciones virtuales, es posible que pueda encontrar su ubicación de la manera más difícil:
- Haga un volcado de memoria completo del proceso.
- Cargue el volcado total de memoria en WinDbg.
- Use el comando
x
para encontrar la dirección de vtable de MyClass:
0:000> x programname!MyClass::`vftable'' 00425c64 programname!MyClass::`vftable'' =
- Utilice el comando
s
para buscar el espacio de direcciones virtuales del proceso (en este ejemplo, 0-2 GB) para los punteros al 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.............
- Utilice el comando
dt
para buscar el desplazamiento vtable de la clase y restarlo de las direcciones devueltas desde la búsqueda. Estas son direcciones posibles para el objeto.
0:000> dt programname!MyClass +0x000 __VFN_table : Ptr32 +0x008 x : Int4B +0x010 y : Float
- Use
dt programname!MyClass 0042b360
para examinar las variables miembro del objeto, probando la hipótesis de que el objeto se encuentra en 0042b360 (o en alguna otra dirección). Es probable que obtenga algunos resultados positivos falsos, como hice anteriormente, pero al inspeccionar las variables de los miembros puede averiguar cuál es su singleton.
Esta es una técnica general para encontrar objetos C ++, y es un poco exagerado cuando podrías desmontar MyClass::getInstance
.