【问题标题】:How can I see how a C++ class gets laid out in memory with gdb?如何使用 gdb 查看 C++ 类如何在内存中布局?
【发布时间】:2011-10-12 20:56:13
【问题描述】:

我有一个程序的调试版本(V8 JavaScript VM),我想了解某些类的实例是如何在内存中布局的。我可以像这样漂亮地打印结构:

(gdb) print thread_local
$6 = {
  blocks_ = {
    data_ = 0x868ceb0,
    capacity_ = 7,
    length_ = 1
  },
  entered_contexts_ = {
    data_ = 0x868d828,
    capacity_ = 1,
    length_ = 1
  },
  saved_contexts_ = {
    data_ = 0x868d838,
    capacity_ = 1,
    length_ = 1
  },
  spare_ = 0x0,
  ignore_out_of_memory_ = false,
  call_depth_ = 1,
  handle_scope_data_ = {
    next = 0x0,
    limit = 0x0,
    level = 0
  }
}

但我想知道这些不同的成员(块、entered_contexts 等)相对于对象的起始位置在物理上的位置。在基于 Solaris 的系统上,mdb 可以对 C 结构执行此操作,如下所示:

> ::print -at port_event_t
0 port_event_t {
    0 int portev_events 
    4 ushort_t portev_source 
    6 ushort_t portev_pad 
    8 uintptr_t portev_object 
    10 void *portev_user 
}

在该示例中,每个字段的前缀都是从结构开始的偏移量。我想为 C++ 类做同样的事情。 gdb 必须拥有这些信息才能打印出结构成员,但是有什么方法可以查看它?

或者,是否有其他方法可以为正在运行的程序执行此操作?

【问题讨论】:

    标签: c++ gdb


    【解决方案1】:

    您始终可以打印出每个成员的地址,并打印出this 来自己弄清楚(您使用& 来获取成员地址,就像使用语言本身一样)。

    【讨论】:

      【解决方案2】:

      我希望我知道。

      您可以使用 ptype 列出成员。然后你可以像这样编造一个穷人的偏移量:

      (gdb) p/a &((my_struct_*)0)->my_member
      
      (gdb) p/a &((struct sk_buff*)0)->iif
      $7 = 0x74
      

      【讨论】:

        【解决方案3】:

        2020年现代gdb版本有ptype /o:

        (gdb) ptype /o 'sead::MethodTreeNode'
        /* offset    |  size */  type = class sead::MethodTreeNode : public sead::IDisposer, public sead::TTreeNode<sead::MethodTreeNode*>, public sead::INamable {
                                 private:
        /*   88      |    32 */    class sead::StorageFor<sead::AnyDelegate> [with T = class sead::AnyDelegate] {
                                     private:
        /*   88      |    32 */        u8 mStorage[32];
        
                                       /* total size (bytes):   32 */
                                   } mDelegateHolder;
        /*  120      |     8 */    class sead::CriticalSection *mCriticalSection;
        /*  128      |     4 */    u32 mPriority;
        /*  132      |     4 */    sead::BitFlag32 mPauseFlag;
        /*  136      |     8 */    PauseEventDelegate *mPauseEventDelegate;
        /*  144      |     8 */    void *mUserID;
        
                                   /* total size (bytes):  152 */
                                 }
        
        

        它甚至会显示结构/类成员变量的布局和总大小。

        为了记录,这是原始的 C++ 代码:

        class MethodTreeNode : public IDisposer, public TTreeNode<MethodTreeNode*>, public INamable
        {
            // ...
            using PauseEventDelegate = IDelegate2<MethodTreeNode*, PauseFlag>;
            // ...
            StorageFor<sead::AnyDelegate> mDelegateHolder;
            mutable CriticalSection* mCriticalSection;
            u32 mPriority;
            BitFlag32 mPauseFlag;
            PauseEventDelegate* mPauseEventDelegate;
            void* mUserID;
        };
        

        我还没有弄清楚如何让它以十六进制打印成员偏移量...

        【讨论】:

          【解决方案4】:

          我知道的唯一方法是x /&lt;number of bytes&gt;x &lt;variable name&gt;

          这会给你一个十六进制转储,然后由你来阅读结构。

          【讨论】:

            【解决方案5】:

            使用pahole(不是 GDB 的一部分)。

            另一种可能性是pahole.py(尚未提交)。

            【讨论】:

            • 谢谢。这看起来很有趣。
            猜你喜欢
            • 2016-07-31
            • 2011-12-12
            • 2012-05-29
            • 2012-06-15
            • 2011-12-02
            • 1970-01-01
            • 2014-12-21
            相关资源
            最近更新 更多