2008-11-13 83 views
6

下面是一些代码,我有:VC++如何修改本地静态变量名称?

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

我想看看这个单身的电流值。但是我目前暂停了三个小时的执行,而我暂停的原因是我内存不足。所以我不能在这个方法中放置一个断点来看看它的价值。

那么我的问题是如何从全局范围引用这个instance变量。我试过把它称为MyClass::getInstance::instance,但这不起作用。我猜getInstance必须以某种方式装饰。任何人都知道吗?

这是在Visual Studio 2008中

+0

为什么不去做班级成员?本地静态变量不是调试的最佳选择 – 2008-11-13 21:08:08

+0

什么类的成员? – Owen 2008-11-13 21:08:59

+0

class MyClass { MyClass * instance; MyClass * getInstance(){ return instance; } } – 2008-11-13 21:15:10

回答

4

当然,函数范围的静态变量instance不通过cl.exe /Fm产生.map文件显示,它不会显示出来,当我在WinDbg中使用x programname!*MyClass*,使错位的名称似乎不包含MyClass

选项1:拆下MyClass::getInstance

这种做法似乎更容易:

 
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 

由此我们可以告诉编译器调用的对象$S1。当然,这个名字将取决于你的程序有多少个函数范围的静态变量。

选项2:搜寻记忆的对象

要在@ gbjbaanb的建议扩大,如果MyClass有虚函数,你也许可以找到它的位置艰辛的道路:

  • 制作该进程的完整内存转储。
  • 将完整的内存转储装入WinDbg。
  • 使用x命令查找MyClass的的虚函数表的地址:
 
    0:000> x programname!MyClass::`vftable' 
    00425c64 programname!MyClass::`vftable' = 
  • 使用s命令搜索进程的虚拟地址空间(在这个例子中,0-2GB)为指向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............. 
  • 使用dt命令查找类的vtable偏移量,并从搜索返回的地址中减去该偏移量。这些是该对象的可能地址。
 
    0:000> dt programname!MyClass 
     +0x000 __VFN_table  : Ptr32 
     +0x008 x    : Int4B 
     +0x010 y    : Float 
  • 使用dt programname!MyClass 0042b360检查对象的成员变量,检验假设,即目标位于0042b360(或其他地址)。你可能会得到一些误报,就像我上面做的那样,但通过检查成员变量,你可能能够找出哪一个是你的单身人士。

这是一种用于查找C++对象的常规技术,当您可以反汇编MyClass::getInstance时有点矫枉过正。

1

在gdb中,你可以把一个观察点上的变量重整名称。

例如,具有这样的功能:

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

    return xyz; 
} 

我可以看_ZZ1fvE3xyz(与gcc 3.2.3或4.0.1 GCC作为错位)。

1

该代码只是看起来很危险...... :-)

但无论如何,你的重整名称是要取决于你Calling Convention你发现你的裂伤名字,你需要知道你的编译环境所使用的那么之前调用约定。 MSDN有更多关于调用约定的信息。

除此之外,找到所有关于您的类的信息的一种方法是检查您的对象的前4个字节中的VTable。反向者使用的一个妙用技巧是隐藏的VC++标记reportSingleClassLayout,它以ASCII艺术的方式打印类结构。