代码之家  ›  专栏  ›  技术社区  ›  Owen

VC++如何处理局部静态变量名?

  •  6
  • Owen  · 技术社区  · 17 年前

    以下是我的一些代码:

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

    instance 来自全局范围的变量。我试着把它称为 MyClass::getInstance::instance 但这不起作用。我猜 getInstance

    这是在VisualStudio2008中。

    3 回复  |  直到 17 年前
        1
  •  5
  •   bk1e    17 年前

    函数的作用域是静态的 instance .map cl.exe /Fm ,当我使用 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 . 当然,这个名称将取决于您的程序有多少函数范围的静态变量。

    如有必要,请详述@gbjbaanb的建议 类名

    • 对进程进行完全内存转储。
    • 将完整内存转储加载到WinDbg中。
    • 使用 x
        0:000> x programname!MyClass::`vftable'
        00425c64 programname!MyClass::`vftable' = 
    
    • 使用 s 用于搜索进程的虚拟地址空间(在本例中为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.............
    
    • dt 命令查找类的vtable偏移量,并从搜索返回的地址中减去该偏移量。这些是对象的可能地址。
        0:000> dt programname!MyClass
           +0x000 __VFN_table      : Ptr32 
           +0x008 x                : Int4B
           +0x010 y                : Float
    
    • 使用 dt programname!MyClass 0042b360

    MyClass::getInstance .

        2
  •  1
  •   Nathan Kitchen    17 年前

    在gdb中,您可以在变量的损坏名称上放置一个观察点。

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

    我可以看zz1ffe3xyz(被gcc 3.2.3或gcc 4.0.1弄得乱七八糟)。

        3
  •  1
  •   kervin    17 年前

    Calling Convention 因此,在找到mangle名称之前,您需要知道构建环境使用什么作为调用约定。MSDN有更多关于调用约定的信息。

    除此之外,了解有关类的所有信息的一种方法是检查VTable,它位于对象的前4个字节中。反向器使用的一个漂亮技巧是隐藏的VC++标志 reportSingleClassLayout