c++ 如何在Visual Studio调用堆栈中读取匿名对象的名称?

anauzrmj  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(83)

在调用堆栈中跟踪匿名访问对我来说一直是一个挑战,所以我写了一些沙箱代码来处理这个问题:

int main() {
  [] {
    std::cout << "Hello World!\n";
  } ();

  [] {
    std::cout << "Hello World!\n";
  } ();
}

字符串
在这里,我调用了匿名的匿名函数。我把断点放在匿名函数的主体中,并检查了调用堆栈。我看到的是:

`main'::`2'::<lambda_1>::operator()()
`main'::`2'::<lambda_2>::operator()()


我主要是通过在不同的函数或名称空间中使用匿名的XML来找出记录的含义。
有一件事我不能理解的是这个数字2分隔函数main的名称和lambda <lambda_1>的标签。有人知道这个数字是什么意思吗?

bwleehnv

bwleehnv1#

``2'`来自标识嵌套块作用域的mangled名称的一部分。示例(godbolt):

void foo() 
{
  [] { int i = 11; } (); // ??R<lambda_1>@?1??foo@@YAXXZ@QEBA@XZ => `foo'::`2'::<lambda_1>::operator()
  [] { int i = 12; } (); // ??R<lambda_2>@?1??foo@@YAXXZ@QEBA@XZ => `foo'::`2'::<lambda_2>::operator()

  {
    [] { int i = 21; } (); // ??R<lambda_3>@?2??foo@@YAXXZ@QEBA@XZ => `foo'::`3'::<lambda_3>::operator()
    [] { int i = 21; } (); // ??R<lambda_4>@?2??foo@@YAXXZ@QEBA@XZ => `foo'::`3'::<lambda_4>::operator()
  }

  {
    [] { int i = 31; } (); // ??R<lambda_5>@?3??foo@@YAXXZ@QEBA@XZ => `foo'::`4'::<lambda_5>::operator()
    [] { int i = 31; } (); // ??R<lambda_6>@?3??foo@@YAXXZ@QEBA@XZ => `foo'::`4'::<lambda_6>::operator()

    {
        [] { int i = 41; } (); // ??R<lambda_7>@?4??foo@@YAXXZ@QEBA@XZ => `foo'::`5'::<lambda_7>::operator()
    }
  }

  {
    [] { int i = 51; } (); // ??R<lambda_8>@?5??foo@@YAXXZ@QEBA@XZ => `foo'::`6'::<lambda_8>::operator()
    [] { int i = 52; } (); // ??R<lambda_9>@?5??foo@@YAXXZ@QEBA@XZ => `foo'::`6'::<lambda_9>::operator()
  }

  [] { int i = 13; } (); // ??R<lambda_8>@?1??foo@@YAXXZ@QEBA@XZ => `foo'::`2'::<lambda_8>::operator()
}

字符串
所以2'`表示函数级块,更高的数字枚举内部块。这只是MSVC使用的嵌套元素的正常(未记录)mangling方案。即,这只是编译器命名符号的方式。 关于mangling方案,请参阅此链接以获取更多信息。数字2'本身来自??R<lambda_1>@?1??foo@@YAXXZ@QEBA@XZ中的?1部分。它是一个“编码数字”。在这里,mangled名称中的数字1在demangled名称中变为2(参见此处)。此外,请参见此处获取LLVM demangler中的相应代码。 函数级别块以mangled数字1(demangled ``2')而不是0开始,因为在特殊函数中可能有更高级别的块,即构造函数中的初始化列表。例如(godbolt):

struct Struct{
    void (*func)();
    Struct(): func(
      // ?<lambda_invoker_cdecl>@<lambda_1_>@?0???0Struct@@QEAA@XZ@SA@XZ 
      // => `Struct::Struct'::`1'::<lambda_1_>::<lambda_invoker_cdecl>
      [](){ int i = 0; }
    ) {}
};
void foo() {
  Struct s;
}


这里你得到了一个mangled 0,因此是一个demangled ``1'。同样,在[function try blocks](https://en.cppreference.com/w/cpp/language/function-try-block)中,mangled level0`可能会出现。例如(godbolt):

void foo() try
{
}
catch(...)
{
    [](){ int i = 111; }();
}


在这里,反汇编包含符号?catch$0@?0??foo@@YAXXZ@4HA(demangled intvoid __cdecl foo(void)'::1'::catch$0)来表示catch。然而,catch中的lambda具有mangled嵌套级别3(demangled ``4'`)。(我猜+1表示函数体,+1表示catch声明符。)

相关问题