查看变量有以下几种常用方式:
仍以我们上篇 : 《windbg : x 命令》中的代码作为示例来讲解使用。
源码:
#include <iostream>
using namespace std;
struct JKGirl{
std::string name;
int age;
friend ostream& operator <<(ostream& o,const JKGirl& that)
{
return o << that.name << " is " << that.age << " years old.";
}
};
int factorical(unsigned int n){
static int result = 1;
if(n <= 0 ) return result; // 递归结束条件
result *= n; // 算子
return factorical(--n) ; // 递归
}
int main()
{
int num = 20;
double f = 30.25;
int result = factorical(3);
cout << result << endl;
JKGirl girl = {"Anna",18};
cout << girl << endl;
return 0;
}
一、通过windbg “局部变量”窗口查看
“局部变量”窗口显示有关当前范围内所有局部变量的信息。
若要打开或切换到“局部变量”窗口,请在“WinDbg”窗口中的“ 视图 ”菜单上,选择“ 局部变量”。 (还可以按 Alt+3 或选择工具栏上的 “局部变量 ”按钮。Alt+SHIFT+3 关闭“局部变量”窗口。)
忽略左侧乱七八糟的加密字符串,这是博主电脑加密,导致源码显示乱码的问题。(摸鱼被你们发现了~)
二、通过在“调试器命令”窗口中输入 dv 命令或 dt 命令来查看局部变量和参数
0:000> dv
num = 0n20
girl = struct JKGirl
f = 30.25
result = 0n6
通过dv
指令,查看当前栈上的所有局部变量的值
通过dt 变量
指令,查看指定局部变量的数据类型
dv指令貌似直接给我们显示了当前栈上的部分局部变量的信息,为什么是部分呢?这个结构体变量 girl = struct JKGirl
它只告诉了我这是一个结构体,没具体显示每个成员的值啊,咋整?
结构体变量值的查询
我们采用如下指令可以具体查询结构体变量的值:
先通过dt
指令获取结构体变量的地址
0:000> dt girl
Local var @ 0xe32d6ffad8 Type JKGirl
+0x000 name : std::basic_string<char,std::char_traits<char>,std::allocator<char> >
+0x028 age : 0n18
现在我们拿到了girl
变量的地址 0xe32d6ffad8
,注意往下看,同时显示了girl
中两个成员变量的地址偏移。
girl.name
的偏移是 0x000
,首地址即首个成员变量的地址
girl.age
的偏移是 0x028
,那么girl.age
可以通过地址0xe32d6ffad8+0x028
进行访问
拿到了变量的地址,那这件事就好办了。
我们通过dx
指令来访问目标地址。
0:000> dx -r1 (*((WD01!JKGirl *)0xe32d6ffad8))
(*((WD01!JKGirl *)0xe32d6ffad8)) [Type: JKGirl]
[+0x000] name : "Anna" [Type: std::basic_string<char,std::char_traits<char>,std::allocator<char> >]
[+0x028] age : 18 [Type: int]
这里我们使用了 dx -r1
递归显示变量girl
的所有成员。
比较看看,如果使用 dx -r2
会怎样?
0:000> dx -r2 (*((WD01!JKGirl *)0xe32d6ffad8))
(*((WD01!JKGirl *)0xe32d6ffad8)) [Type: JKGirl]
[+0x000] name : "Anna" [Type: std::basic_string<char,std::char_traits<char>,std::allocator<char> >]
[<Raw View>] [Type: std::basic_string<char,std::char_traits<char>,std::allocator<char> >]
[size] : 0x4 [Type: unsigned __int64]
[capacity] : 0xf [Type: unsigned __int64]
[allocator] : allocator [Type: std::_Compressed_pair<std::allocator<char>,std::_String_val<std::_Simple_types<char> >,1>]
[0] : 65 'A' [Type: char]
[1] : 110 'n' [Type: char]
[2] : 110 'n' [Type: char]
[3] : 97 'a' [Type: char]
[+0x028] age : 18 [Type: int]
简单说一下,dx -r1
是简单打印模式; dx -r[n>1]
是详细模式。
如果需要查看指定结构体成员的值,可以通过 dx 变量.成员变量的方式
来查看,如下示例:
0:000> dx girl.name
girl.name : "Anna" [Type: std::basic_string<char,std::char_traits<char>,std::allocator<char> >]
[<Raw View>] [Type: std::basic_string<char,std::char_traits<char>,std::allocator<char> >]
[size] : 0x4 [Type: unsigned __int64]
[capacity] : 0xf [Type: unsigned __int64]
[allocator] : allocator [Type: std::_Compressed_pair<std::allocator<char>,std::_String_val<std::_Simple_types<char> >,1>]
[0] : 65 'A' [Type: char]
[1] : 110 'n' [Type: char]
[2] : 110 'n' [Type: char]
[3] : 97 'a' [Type: char]
0:000> dx girl.age
girl.age : 18 [Type: int]
ok,到这里就解决了我们在调试过程中查看结构体成员变量的难点
扩展讲讲 dx
指令
在windbg
中,dx
(display expression)是一个非常强大和灵活的命令,用于显示和解析复杂的数据结构和表达式。使用dx
命令,可以直接在命令行中执行表达式,并以易于阅读的方式显示结果。
dx
命令的基本语法为:
dx [options] expression
以下是dx
命令的一些常用选项:
/t
:指定要显示的数据类型,例如/t MyStruct
。/r
:以递归方式显示对象的所有成员,包括嵌套结构体和指针。/v
:显示详细的调试信息,包括成员的偏移量和大小。/g
:显示全局符号,例如全局变量和函数。/v
:显示详细的调试信息,包括成员的偏移量和大小。/f
:根据指定的格式化字符串显示结果。
下面是一些例子,以演示dx
命令的用法:
- 查看一个变量的值:
dx myVar
- 查看一个结构体的成员:
dx myStruct.Member
- 以递归方式查看一个结构体的所有成员:
dx /r myStruct
- 使用格式化字符串查看一个结构体的成员和其值:
dx /f "Member1: %i, Member2: %s" myStruct
- 查看一个数组变量的元素:
dx myArray[0]
- 查看一个指针变量的指向的结构体的成员:
dx myPtr->Member
需要注意的是,在使用dx
命令之前,需要先加载符号信息,以便能够正确解析表达式和数据类型。可以使用命令.symfix
或.reload /f
来加载符号信息。