使用WinDbg在堆上查找所有类型为X的C ++对象

时间:2010-06-26 11:31:22

标签: windbg

我正在尝试在堆中找到module!SomeClass类型的所有对象。我认为像这样的命令会起作用:

> s -v 0 L?0xfffffff module!SomeClass

但唉,事实并非如此。如果我知道如何找到该类的vtable地址,那么我可以搜索内存以获取对该vtable的引用,但我也没有太多运气找到它。我该怎么办?

2 个答案:

答案 0 :(得分:10)

0:000> x module!SomeClass*table*
0:000> !heap -srch 'address_of_vtable'

答案 1 :(得分:0)

class Polygon {
protected:
    int width, height;
public:
    virtual int area()
    {
        return 0;
    }
};

class Rectangle : public Polygon {
public:
    int area()
    {
        return width * height;
    }
};

class Triangle : public Polygon {
public:
    int area()
    {
        return (width * height / 2);
    }
};


class RectangleTriangle : public Rectangle, Triangle //RectangleTriangle  <-- This class will have two Vtables for each base class
{
public:
    int area()
    {
        return (2* 3/ 2);
    }
};

int main() {
    RectangleTriangle *rect = new RectangleTriangle();
    Triangle trgl;
    Polygon poly;
    return 0;
}

我们从vtable开始的原因是因为任何继承虚函数的对象都会有一个vtable指针,该指针基本上是类的静态变量。因此,当在堆中创建对象时,该类的每个对象都应该引用此vtable位置。所以从vtable指针我们基本上试图掌握对象本身。

0:000> x Win32Sample!RectangleTriangle*table*
00007ff7`81ed3288 Win32Sample!RectangleTriangle::`vftable' = <function> *[2] <-- one for each base class
00007ff7`81ed3278 Win32Sample!RectangleTriangle::`vftable' = <function> *[2] <-- one for each base class

0:000> !heap -srch 00007ff7`81ed3288  // <-- We are asking !heap "who owns a pointer to this vtable in the entire process heap"
    _HEAP @ 1e5ed710000
              HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state
        000001e5ed716620 0006 0000  [00]   000001e5ed716630    00021 - (busy)
          Win32Sample!RectangleTriangle::`vftable'

0:000> !heap -srch 00007ff7`81ed3278 // <-- We are asking !heap "who owns a pointer to this vtable in the entire process heap"
    _HEAP @ 1e5ed710000
              HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state
        000001e5ed716620 0006 0000  [00]   000001e5ed716630    00021 - (busy)
          Win32Sample!RectangleTriangle::`vftable'

UserPtr基本上是堆管理器为新运算符返回的内存块的开始。这就是为什么UserPtr并不意味着包含这个值的内存位置而是它是堆块的开始,因此在两个vtable中值都相同000001e5ed716630

0:000> dt Win32Sample!RectangleTriangle 000001e5ed716630
   +0x000 __VFN_table : 0x00007ff7`81ed3278 
   +0x008 width            : 0n0
   +0x00c height           : 0n0
   +0x010 __VFN_table : 0x00007ff7`81ed3288 
   +0x018 width            : 0n0
   +0x01c height           : 0n0

我们不能使用s命令来搜索vtable指针和堆中的对象,因为堆块不是连续的!