WINDBG:查看未命名命名空间中变量的值
WINDBG: Viewing values of variables in unnamed namespace
进入 Windbg 后,是否有某种技巧可以查看 未命名 命名空间中变量的值?我这样定位变量:
0:000> x mod!ns::*myvar*
70f7afc6 mod!ns::`anonymous namespace'::`dynamic initializer for 'myvar'' (void)
717bb799 mod!ns::`anonymous namespace'::`dynamic atexit destructor for 'myvar'' (void)
71a00718 mod!ns::`anonymous namespace'::myvar = <no type information>
myvar
基本上是一个 std::map
并且有一个可用的调试器可视化工具 (natvis),因此 ?? myvar
应该显示一些可用的东西。然而,由于匿名命名空间介于两者之间,我似乎无法找出正确的语法来显示 myvar
中的值。
有什么想法吗?
从历史上看,windbg 在实现这些花哨的显示方面落后了一两英里
那是你的名字 space 嵌套?。
我假设是,因为你在 module mod!ns::
之后有一个 ns
如果不是这种情况 x mymap 将生成可点击的 dml link
如果它是嵌套的,它会正确显示类型 windbg 会吐出 没有可用的类型信息
在那种情况下,您可以使用指针将它们转换为实际类型,例如 mod!std::map..........xxx...
这是在 windbg 下编译和执行的人为源代码,演示了一些可能性
第一个文件的来源,其中包含一个未命名的 ns 和一个命名的嵌套未命名 ns,还引用了另一个包含匿名名称的文件space
#include "anonall.h"
namespace {
map<char, const char*> mymap;
const char *Greek_Alphabets[ALLOCSIZ] = { "Alp","Bet","Gam","Del","Eps" };
}
namespace ns {
namespace {
map<char, const char*> mymap;
const char *Greek_Alphabets[ALLOCSIZ]={
"Alpha","Beta","Gamma","Delta","Epsilon" };
}
}
void anonnsptwo(void);
void anonnsptre(void) {
cout << "\nfrom Anonymous NS Map in " << __FILE__ << " " << __LINE__ << "\n\n";
for (int i = 0; i < ALLOCSIZ; i++) {
mymap.insert(pair<char, const char*>(char('M' + i), Greek_Alphabets[i]));
}
map<char, const char*>::iterator iter = mymap.begin();
for (iter; iter != mymap.end(); iter++)
cout << iter->first << " = " << iter->second << "\n";
}
int main(void) {
anonnsptre();
cout << "\nfrom Anonymous NS Map in " << __FILE__ << " " << __LINE__ << "\n\n";
for (int i = 0; i < ALLOCSIZ; i++) {
ns::mymap.insert(pair<char, const char*>(char('A'+i),ns::Greek_Alphabets[i]));
}
map<char, const char*>::iterator iter = ns::mymap.begin();
for (iter; iter != ns::mymap.end(); iter++)
cout << iter->first << " = " << iter->second << "\n";
anonnsptwo();
return 0;
}
第一个文件引用的第二个文件的来源
#include "anonall.h"
namespace ns {
namespace {
map<char, const char*> mymap;
const char *Greek_Alphabets[ALLOCSIZ]={"Zeta","Eta","Theta","Iota","Kappa"};
}
}
void anonnsptwo(void) {
cout << "\nfrom Anonymous Namespace Map in " << __FILE__ << "\n\n";
for (int i = 0; i < ALLOCSIZ; i++) {
ns::mymap.insert(pair<char, const char*>(char('Z'-i),ns::Greek_Alphabets[i]));
}
map<char, const char*>::iterator iter = ns::mymap.begin();
for (iter; iter != ns::mymap.end(); iter++)
cout << iter->first << " = " << iter->second << "\n";
}
公共头文件内容
#pragma once
#include <iostream>
#include <map>
#define ALLOCSIZ 5
using namespace std;
使用 vs community 2017 (15.6.4) cmd 提示编译和 linked
:\>echo off
ls
anonall.h anonone.cpp anontwo.cpp
cl /Zi /W4 /analyze /EHsc /Od /nologo anonone.cpp anontwo.cpp /link /release /nologo
anonone.cpp
anontwo.cpp
Compiling...
Generating Code...
ls
anonall.h anonone.obj anontwo.obj
anonone.cpp anonone.pdb vc140.pdb
anonone.exe anontwo.cpp
anonone.nativecodeanalysis.xml anontwo.nativecodeanalysis.xml
执行二进制文件
anonone.exe
from Anonymous NS Map in anonone.cpp 15
M = Alp
N = Bet
O = Gam
P = Del
Q = Eps
from Anonymous NS Map in anonone.cpp 25
A = Alpha
B = Beta
C = Gamma
D = Delta
E = Epsilon
from Anonymous Namespace Map in anontwo.cpp
V = Kappa
W = Iota
X = Theta
Y = Eta
Z = Zeta
使用 cdb 只是为了显示结果而无需用户干预
如果使用 windbg 而不是 cdb,x*!*mymap 的结果将是可点击的 links
注意大小 = 5 并注意其他两个没有类型信息的匿名 mymaps
(关于如何打印这些 mymaps 的问题如下)
在第一个文件上设置断点return(程序结束)
grep -in ret.* anonone.cpp
33: return 0; << 行号为 33
enabling line no info 在 src 行上设置条件延迟中断,并在遇到该中断时打印 x 命令的结果并退出
>cdb -c ".lines;bu `anonone.cpp:33` \"x *!*mymap*\";g;q" anonone.exe
e
cdb -c ".lines;bu `anonone.cpp:33` \"x *!*mymap*\";g;q" anonone.exe
Microsoft (R) Windows Debugger Version 10.0.16299.15 X86
0:000> cdb: Reading initial command '.lines;bu `anonone.cpp:33` "x *!*mymap*";g;q'
snipp======================
0118b938 anonone!mymap = { size=0x5 }
01175198 anonone!mymap$initializer$ = 0x01101040
011742c0 anonone!`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
01101040 anonone!`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
011742e0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
011742d0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
01101080 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
01101060 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
0118b930 anonone!ns::`anonymous namespace'::mymap = <no type information>
0118b960 anonone!ns::`anonymous namespace'::mymap = <no type information>
quit:
您现在可以将 mymap @ 0x0118b960 和 0x0118b930 的地址都转换为 std::map
(做 x anonone!std::map 点击 tab tab tab 找到类型信息,使它成为一个指针并粘贴地址,并使用 dx 表达式求值器来获得显示)
类似于 dx (anonone!std:map......xx..yy..zz *) 0x0118b960
ntdll!LdrpDoDebuggerBreak+0x2c:
771d05a6 cc int 3
Processing initial command '$$>a< displayanon.txt'
0:000> $$>a< displayanon.txt
ModLoad: 6b450000 6b453000 C:\Windows\system32\api-ms-win-core-synch-l1-2-0.DLL
00d6b938 anonone!mymap = { size=0x5 }
00d55198 anonone!mymap$initializer$ = 0x00ce1040
00d542c0 anonone!`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
00ce1040 anonone!`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
00d542e0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
00d542d0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
00ce1080 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
00ce1060 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
00d6b930 anonone!ns::`anonymous namespace'::mymap = <no type information>
00d6b960 anonone!ns::`anonymous namespace'::mymap = <no type information>
this is the type which you can get by using x {mod}!{std::map {wildcard}}
class std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > >
+0x000 _Mypair :
mymap : { size=0x5 }
snipped
[0x0] : 77 'M', "Alp" [Type:
[0x1] : 78 'N', "Bet" [Type:
[0x2] : 79 'O', "Gam" [Type:
[0x3] : 80 'P', "Del" [Type:
[0x4] : 81 'Q', "Eps" [Type:
0:000> dx ( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b930
( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b930
snipped
[0x1] : 65 'A', "Alpha" [Type:
[0x2] : 66 'B', "Beta" [Type:
[0x3] : 67 'C', "Gamma" [Type:
[0x4] : 68 'D', "Delta" [Type:
[0x5] : 69 'E', "Epsilon" [Type:
0:000> dx ( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b960
( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b960
snipped
[0x1] : 86 'V', "Kappa" [Type: std::pair<char const ,char const *>]
[0x2] : 87 'W', "Iota" [Type: std::pair<char const ,char const *>]
[0x3] : 88 'X', "Theta" [Type: std::pair<char const ,char const *>]
[0x4] : 89 'Y', "Eta" [Type: std::pair<char const ,char const *>]
[0x5] : 90 'Z', "Zeta" [Type: std::pair<char const ,char const *>]
进入 Windbg 后,是否有某种技巧可以查看 未命名 命名空间中变量的值?我这样定位变量:
0:000> x mod!ns::*myvar*
70f7afc6 mod!ns::`anonymous namespace'::`dynamic initializer for 'myvar'' (void)
717bb799 mod!ns::`anonymous namespace'::`dynamic atexit destructor for 'myvar'' (void)
71a00718 mod!ns::`anonymous namespace'::myvar = <no type information>
myvar
基本上是一个 std::map
并且有一个可用的调试器可视化工具 (natvis),因此 ?? myvar
应该显示一些可用的东西。然而,由于匿名命名空间介于两者之间,我似乎无法找出正确的语法来显示 myvar
中的值。
有什么想法吗?
从历史上看,windbg 在实现这些花哨的显示方面落后了一两英里
那是你的名字 space 嵌套?。
我假设是,因为你在 module mod!ns::
之后有一个 ns如果不是这种情况 x mymap 将生成可点击的 dml link 如果它是嵌套的,它会正确显示类型 windbg 会吐出 没有可用的类型信息
在那种情况下,您可以使用指针将它们转换为实际类型,例如 mod!std::map..........xxx...
这是在 windbg 下编译和执行的人为源代码,演示了一些可能性
第一个文件的来源,其中包含一个未命名的 ns 和一个命名的嵌套未命名 ns,还引用了另一个包含匿名名称的文件space
#include "anonall.h"
namespace {
map<char, const char*> mymap;
const char *Greek_Alphabets[ALLOCSIZ] = { "Alp","Bet","Gam","Del","Eps" };
}
namespace ns {
namespace {
map<char, const char*> mymap;
const char *Greek_Alphabets[ALLOCSIZ]={
"Alpha","Beta","Gamma","Delta","Epsilon" };
}
}
void anonnsptwo(void);
void anonnsptre(void) {
cout << "\nfrom Anonymous NS Map in " << __FILE__ << " " << __LINE__ << "\n\n";
for (int i = 0; i < ALLOCSIZ; i++) {
mymap.insert(pair<char, const char*>(char('M' + i), Greek_Alphabets[i]));
}
map<char, const char*>::iterator iter = mymap.begin();
for (iter; iter != mymap.end(); iter++)
cout << iter->first << " = " << iter->second << "\n";
}
int main(void) {
anonnsptre();
cout << "\nfrom Anonymous NS Map in " << __FILE__ << " " << __LINE__ << "\n\n";
for (int i = 0; i < ALLOCSIZ; i++) {
ns::mymap.insert(pair<char, const char*>(char('A'+i),ns::Greek_Alphabets[i]));
}
map<char, const char*>::iterator iter = ns::mymap.begin();
for (iter; iter != ns::mymap.end(); iter++)
cout << iter->first << " = " << iter->second << "\n";
anonnsptwo();
return 0;
}
第一个文件引用的第二个文件的来源
#include "anonall.h"
namespace ns {
namespace {
map<char, const char*> mymap;
const char *Greek_Alphabets[ALLOCSIZ]={"Zeta","Eta","Theta","Iota","Kappa"};
}
}
void anonnsptwo(void) {
cout << "\nfrom Anonymous Namespace Map in " << __FILE__ << "\n\n";
for (int i = 0; i < ALLOCSIZ; i++) {
ns::mymap.insert(pair<char, const char*>(char('Z'-i),ns::Greek_Alphabets[i]));
}
map<char, const char*>::iterator iter = ns::mymap.begin();
for (iter; iter != ns::mymap.end(); iter++)
cout << iter->first << " = " << iter->second << "\n";
}
公共头文件内容
#pragma once
#include <iostream>
#include <map>
#define ALLOCSIZ 5
using namespace std;
使用 vs community 2017 (15.6.4) cmd 提示编译和 linked
:\>echo off
ls
anonall.h anonone.cpp anontwo.cpp
cl /Zi /W4 /analyze /EHsc /Od /nologo anonone.cpp anontwo.cpp /link /release /nologo
anonone.cpp
anontwo.cpp
Compiling...
Generating Code...
ls
anonall.h anonone.obj anontwo.obj
anonone.cpp anonone.pdb vc140.pdb
anonone.exe anontwo.cpp
anonone.nativecodeanalysis.xml anontwo.nativecodeanalysis.xml
执行二进制文件
anonone.exe
from Anonymous NS Map in anonone.cpp 15
M = Alp
N = Bet
O = Gam
P = Del
Q = Eps
from Anonymous NS Map in anonone.cpp 25
A = Alpha
B = Beta
C = Gamma
D = Delta
E = Epsilon
from Anonymous Namespace Map in anontwo.cpp
V = Kappa
W = Iota
X = Theta
Y = Eta
Z = Zeta
使用 cdb 只是为了显示结果而无需用户干预
如果使用 windbg 而不是 cdb,x*!*mymap 的结果将是可点击的 links
注意大小 = 5 并注意其他两个没有类型信息的匿名 mymaps
(关于如何打印这些 mymaps 的问题如下)
在第一个文件上设置断点return(程序结束)
grep -in ret.* anonone.cpp
33: return 0; << 行号为 33
enabling line no info 在 src 行上设置条件延迟中断,并在遇到该中断时打印 x 命令的结果并退出
>cdb -c ".lines;bu `anonone.cpp:33` \"x *!*mymap*\";g;q" anonone.exe e
cdb -c ".lines;bu `anonone.cpp:33` \"x *!*mymap*\";g;q" anonone.exe
Microsoft (R) Windows Debugger Version 10.0.16299.15 X86
0:000> cdb: Reading initial command '.lines;bu `anonone.cpp:33` "x *!*mymap*";g;q'
snipp======================
0118b938 anonone!mymap = { size=0x5 }
01175198 anonone!mymap$initializer$ = 0x01101040
011742c0 anonone!`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
01101040 anonone!`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
011742e0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
011742d0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
01101080 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
01101060 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
0118b930 anonone!ns::`anonymous namespace'::mymap = <no type information>
0118b960 anonone!ns::`anonymous namespace'::mymap = <no type information>
quit:
您现在可以将 mymap @ 0x0118b960 和 0x0118b930 的地址都转换为 std::map
(做 x anonone!std::map 点击 tab tab tab 找到类型信息,使它成为一个指针并粘贴地址,并使用 dx 表达式求值器来获得显示)
类似于 dx (anonone!std:map......xx..yy..zz *) 0x0118b960
ntdll!LdrpDoDebuggerBreak+0x2c:
771d05a6 cc int 3
Processing initial command '$$>a< displayanon.txt'
0:000> $$>a< displayanon.txt
ModLoad: 6b450000 6b453000 C:\Windows\system32\api-ms-win-core-synch-l1-2-0.DLL
00d6b938 anonone!mymap = { size=0x5 }
00d55198 anonone!mymap$initializer$ = 0x00ce1040
00d542c0 anonone!`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
00ce1040 anonone!`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
00d542e0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
00d542d0 anonone!ns::`anonymous namespace'::`dynamic atexit destructor for 'mymap'' (void)
00ce1080 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
00ce1060 anonone!ns::`anonymous namespace'::`dynamic initializer for 'mymap'' (void)
00d6b930 anonone!ns::`anonymous namespace'::mymap = <no type information>
00d6b960 anonone!ns::`anonymous namespace'::mymap = <no type information>
this is the type which you can get by using x {mod}!{std::map {wildcard}}
class std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > >
+0x000 _Mypair :
mymap : { size=0x5 }
snipped
[0x0] : 77 'M', "Alp" [Type:
[0x1] : 78 'N', "Bet" [Type:
[0x2] : 79 'O', "Gam" [Type:
[0x3] : 80 'P', "Del" [Type:
[0x4] : 81 'Q', "Eps" [Type:
0:000> dx ( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b930
( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b930
snipped
[0x1] : 65 'A', "Alpha" [Type:
[0x2] : 66 'B', "Beta" [Type:
[0x3] : 67 'C', "Gamma" [Type:
[0x4] : 68 'D', "Delta" [Type:
[0x5] : 69 'E', "Epsilon" [Type:
0:000> dx ( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b960
( std::map<char,char const *,std::less<char>,std::allocator<std::pair<char const ,char const *> > > *) 0x00d6b960
snipped
[0x1] : 86 'V', "Kappa" [Type: std::pair<char const ,char const *>]
[0x2] : 87 'W', "Iota" [Type: std::pair<char const ,char const *>]
[0x3] : 88 'X', "Theta" [Type: std::pair<char const ,char const *>]
[0x4] : 89 'Y', "Eta" [Type: std::pair<char const ,char const *>]
[0x5] : 90 'Z', "Zeta" [Type: std::pair<char const ,char const *>]