这是我的一些代码:
MyClass* MyClass::getInstance()
{
static MyClass instance;
return &instance;
}
我想研究一下这个单身人士的当前价值。但我现在暂停执行三个小时,而我暂停的原因是我失去了记忆。所以我不能在这个方法中设置一个断点来看看它的价值。
我的问题是如何从全局范围引用此instance
变量。我曾尝试将其称为MyClass::getInstance::instance
,但这不起作用。我猜测getInstance
必须以某种方式进行装饰。谁知道怎么做?
这是在Visual Studio 2008中。
答案 0 :(得分:4)
好吧,函数范围的静态instance
变量没有显示在由.map
生成的cl.exe /Fm
文件中,并且当我使用{{1}时它不显示在WinDbg中,所以受损的名称似乎根本不包含x programname!*MyClass*
。
选项1:反汇编MyClass
这种方法似乎更容易:
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
由此我们可以看出编译器调用了对象MyClass::getInstance
。当然,这个名称将取决于你的程序有多少函数范围的静态变量。
选项2:搜索对象的内存
要扩展@ gbjbaanb的建议,如果$S1
具有虚拟功能,您可能很难找到其位置:
MyClass
命令查找MyClass的vtable的地址:0:000> x programname!MyClass::`vftable' 00425c64 programname!MyClass::`vftable' =
x
命令搜索进程的虚拟地址空间(在本例中为0-2GB),以获取指向MyClass的vtable的指针: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.............
s
命令查找类的vtable偏移量,并从搜索返回的地址中减去该偏移量。这些是对象的可能地址。0:000> dt programname!MyClass +0x000 __VFN_table : Ptr32 +0x008 x : Int4B +0x010 y : Float
dt
检查对象的成员变量,测试对象位于0042b360(或其他某个地址)的假设。你可能会得到一些误报,就像我上面所做的那样,但通过检查成员变量,你可以找出哪一个是你的单身人士。这是查找C ++对象的一般技术,当您可以反汇编dt programname!MyClass 0042b360
时,它有点矫枉过正。
答案 1 :(得分:1)
在gdb中,您可以在变量的错位名称上放置一个观察点。
例如,使用此功能:
int f() {
static int xyz = 0;
++xyz;
return xyz;
}
我可以观看_ZZ1fvE3xyz(由gcc 3.2.3或gcc 4.0.1修改)。
答案 2 :(得分:1)
那段代码看起来很危险......: - )
但无论如何,你的错位名称将取决于你的Calling Convention所以在你找到你的名字之前你需要知道你的构建环境用作调用约定。 MSDN有关于调用约定的更多信息。
除此之外,查找有关您的类的所有信息的一种方法是检查您的VTable,它位于对象的前4个字节中。反向器使用的一个漂亮技巧是隐藏的VC ++标志reportSingleClassLayout,它以ASCII艺术方式打印类结构。