调试器属性
以下属性用于在使用第三方调试器(如 GDB 或 WinDbg)时增强调试体验。
debugger_visualizer 属性
debugger_visualizer 属性可用于将调试器可视化工具文件嵌入到调试信息中。这使得在调试器中显示值时获得改进的调试器体验。
它使用MetaListNameValueStr 语法指定其输入,并且必须指定为 crate 属性。
在 Natvis 中使用 debugger_visualizer
Natvis 是一个基于 XML 的框架,用于 Microsoft 调试器(如 Visual Studio 和 WinDbg),它使用声明式规则来自定义类型的显示。有关 Natvis 格式的详细信息,请参阅 Microsoft 的Natvis 文档。
此属性仅支持在 -windows-msvc 目标平台上嵌入 Natvis 文件。
Natvis 文件的路径通过 natvis_file 键指定,该路径是相对于 crate 源文件的路径
#![debugger_visualizer(natvis_file = "Rectangle.natvis")]
struct FancyRect {
x: f32,
y: f32,
dx: f32,
dy: f32,
}
fn main() {
let fancy_rect = FancyRect { x: 10.0, y: 10.0, dx: 5.0, dy: 5.0 };
println!("set breakpoint here");
}
而 Rectangle.natvis 包含
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="foo::FancyRect">
<DisplayString>({x},{y}) + ({dx}, {dy})</DisplayString>
<Expand>
<Synthetic Name="LowerLeft">
<DisplayString>({x}, {y})</DisplayString>
</Synthetic>
<Synthetic Name="UpperLeft">
<DisplayString>({x}, {y + dy})</DisplayString>
</Synthetic>
<Synthetic Name="UpperRight">
<DisplayString>({x + dx}, {y + dy})</DisplayString>
</Synthetic>
<Synthetic Name="LowerRight">
<DisplayString>({x + dx}, {y})</DisplayString>
</Synthetic>
</Expand>
</Type>
</AutoVisualizer>
在 WinDbg 下查看时,fancy_rect 变量将如下所示
> Variables:
> fancy_rect: (10.0, 10.0) + (5.0, 5.0)
> LowerLeft: (10.0, 10.0)
> UpperLeft: (10.0, 15.0)
> UpperRight: (15.0, 15.0)
> LowerRight: (15.0, 10.0)
在 GDB 中使用 debugger_visualizer
GDB 支持使用结构化的 Python 脚本,称为 pretty printer(美化打印机/可视化打印器),它描述了类型应如何在调试器视图中可视化。有关 pretty printer 的详细信息,请参阅 GDB 的pretty printing 文档。
在 GDB 下调试二进制文件时,嵌入式 pretty printer 不会自动加载。有两种方法可以启用嵌入式 pretty printer 的自动加载
- 启动 GDB 时带额外参数,以显式添加目录或二进制文件到自动加载安全路径:
gdb -iex "add-auto-load-safe-path safe-path path/to/binary" path/to/binary更多信息,请参阅 GDB 的自动加载文档。 - 在
$HOME/.config/gdb下创建一个名为gdbinit的文件(如果目录不存在,您可能需要创建它)。将以下行添加到该文件中:add-auto-load-safe-path path/to/binary。
这些脚本使用 gdb_script_file 键嵌入,这是一个相对于 crate 源文件的路径。
#![debugger_visualizer(gdb_script_file = "printer.py")]
struct Person {
name: String,
age: i32,
}
fn main() {
let bob = Person { name: String::from("Bob"), age: 10 };
println!("set breakpoint here");
}
而 printer.py 包含
import gdb
class PersonPrinter:
"Print a Person"
def __init__(self, val):
self.val = val
self.name = val["name"]
self.age = int(val["age"])
def to_string(self):
return "{} is {} years old.".format(self.name, self.age)
def lookup(val):
lookup_tag = val.type.tag
if lookup_tag is None:
return None
if "foo::Person" == lookup_tag:
return PersonPrinter(val)
return None
gdb.current_objfile().pretty_printers.append(lookup)
当 crate 的调试可执行文件传递给 GDB 时1,print bob 将显示
"Bob" is 10 years old.
注意:这假设您正在使用 rust-gdb 脚本,该脚本为标准库类型(如 String)配置 pretty printer。
collapse_debuginfo 属性
collapse_debuginfo 属性控制在为调用此宏的代码生成 debuginfo 时,是否将来自宏定义的代码位置折叠成与宏调用点关联的单一位置。
该属性使用MetaListIdents 语法指定其输入,并且只能应用于宏定义。
可接受的选项
#[collapse_debuginfo(yes)]— debuginfo 中的代码位置被折叠。#[collapse_debuginfo(no)]— debuginfo 中的代码位置不被折叠。#[collapse_debuginfo(external)]— debuginfo 中的代码位置仅在宏来自不同的 crate 时被折叠。
external 行为是未带此属性的宏的默认值,除非它们是内置宏。对于内置宏,默认值为 yes。
注意
rustc有一个-C collapse-macro-debuginfoCLI 选项,用于覆盖默认的折叠行为和#[collapse_debuginfo]属性。
#![allow(unused)] fn main() { #[collapse_debuginfo(yes)] macro_rules! example { () => { println!("hello!"); }; } }