VC ++如何破坏本地静态变量名?

时间:2008-11-13 21:02:18

标签: c++ scope

这是我的一些代码:

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

我想研究一下这个单身人士的当前价值。但我现在暂停执行三个小时,而我暂停的原因是我失去了记忆。所以我不能在这个方法中设置一个断点来看看它的价值。

我的问题是如何从全局范围引用此instance变量。我曾尝试将其称为MyClass::getInstance::instance,但这不起作用。我猜测getInstance必须以某种方式进行装饰。谁知道怎么做?

这是在Visual Studio 2008中。

3 个答案:

答案 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具有虚拟功能,您可能很难找到其位置:

  • 对流程进行完整的内存转储。
  • 将完整内存转储装入WinDbg。
  • 使用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艺术方式打印类结构。