在Windbg中,如何在调试时列出枚举值?

Kur*_*son 6 c++ debugging enums windbg

通常,enum值是简单的编译器递增值或直接设置为整数文字,因此可以通过查看源文件轻松推导或直接看到这些值.

但是,有时enum值用于将类内常量设置为等于其他位置定义的值,或者设置为不易复制的编译时表达式的结果.

有没有办法让Windbg向我展示enum那些棘手案件中每个成员的实际价值?

Kur*_*son 9

考虑这个小结构:

struct foo
{
    enum enum1
    {
        enum1_val1_ = 5,
        enum1_val2_,
    };

    enum enum2
    {
        enum2_val1_ = 0x0001,
        enum2_val2_ = 0x0010,
    };

    enum
    {
        // assume these come from complicated compile-time expressions
        some_class_constant_ = 86, 
        another_one_ = 99,
    };
};
Run Code Online (Sandbox Code Playgroud)

最快的方法是使用dt命令,使用开关-r(recurse,你需要列出enum成员)和-v(详细,你需要列出enums):

0:000> dt -r -v foo
LangTestingD!foo
struct foo, 3 elements, 0x1 bytes
Enum enum1,  2 total enums
      enum1_val1_ = 0n5
      enum1_val2_ = 0n6
Enum enum2,  2 total enums
      enum2_val1_ = 0n1
      enum2_val2_ = 0n16
Enum <unnamed-tag>,  2 total enums
      some_class_constant_ = 0n86
      another_one_ = 0n99
Run Code Online (Sandbox Code Playgroud)

您可以看到它列出了每个枚举的值,甚至是未命名的值.多个未命名的枚举都将正确列出.

问题dt -r -v foo在于它列出了以下每个成员foo:所有数据成员,所有函数成员,所有枚举,尝试递归到每个成员并列出成员.如果foo是一个复杂的类,它很容易通过继承,输出将是巨大的,并且很难找到你正在寻找的一个枚举.

所以下一个选项是告诉dt你想要的枚举,具体来说:

0:000> dt foo::enum1
LangTestingD!foo::enum1
   enum1_val1_ = 0n5
   enum1_val2_ = 0n6
Run Code Online (Sandbox Code Playgroud)

好,太棒了!但那个未命名的枚举怎么样?好吧,你说,看看上面的输出,它使用的地方<unnamed-tag>.也许我们可以使用它.

0:000> dt foo::<unnamed-tag>
Couldn't resolve error at 'foo::<unnamed-tag>'
Run Code Online (Sandbox Code Playgroud)

它实际上会工作,但你需要使用一些额外的开关.当您组合-n(以下参数是名称)和-y(将下一个参数作为名称前缀匹配)时,它的工作原理如下:

0:000> dt -n -y foo::<unnamed-tag>
LangTestingD!foo::<unnamed-tag>
   some_class_constant_ = 0n86
Run Code Online (Sandbox Code Playgroud)

但是,仅列出第一个值.更糟糕的是,如果有多个未命名的枚举,则只列出第一个值的第一个值.通常这已经足够了,因为多个未命名的枚举并不常见,但如果您绝对需要它们,则必须使用-r -v并在输出中找到它们.