如何在嵌套Rc<RefCell>的结构体中使用GDB美化打印机?
解决Rust中嵌套
Rc<RefCell<FileSystemNode>>的GDB美化打印机失效问题 我定义了如下FileSystemNode结构体,通过嵌套Rc<RefCell<FileSystemNode>>实现节点与父子节点间的可变和不可变访问:
struct FileSystemNode{ current_directory_path: String, current_directory_name: String, // 需要对节点进行可变和不可变访问 // (从当前节点到子节点,或从子节点的子节点到父节点) parent_directory: Option<Rc<RefCell<FileSystemNode>>>, children: Vec<Rc<RefCell<FileSystemNode>>>, // size为0时表示这是一个目录 size: usize }
但用GDB打印该结构体时,会递归遍历所有父子节点,陷入死循环。为解决这个问题,我编写了如下GDB美化打印机:
class FileSystemNodePrinter: def __init__(self, val): self.val = val def to_string(self): return 'test' def display_hint(self): return 'FileSystemNode'
该打印机已在info pretty-printer中显示注册成功,但实际打印时未生效,输出和未使用美化打印机时一致:
$1 = Rc(strong=1, weak=0) = {value = RefCell(borrow=0) = { value = advent_of_code_2022::day7::FileSystemNode { current_directory_path: "/", current_directory_name: "", parent_directory: core::option::Option<alloc::rc::Rc<core::cell::RefCell<advent_of_code_2022::day7::FileSystemNode>>>::none, children: Vec(size=0), size: 0}, borrow = 0}, strong = 1, weak = 0}
我推测问题出在FileSystemNode被嵌套在Rc<RefCell>中,现寻求解决方法。以下是完整复现代码及配置:
复现步骤
Rust完整代码
use std::cell::RefCell; use std::rc::Rc; struct FileSystemNode{ current_directory_path: String, current_directory_name: String, // 需要对节点进行可变和不可变访问 // (从当前节点到子节点,或从子节点的子节点到父节点) parent_directory: Option<Rc<RefCell<FileSystemNode>>>, children: Vec<Rc<RefCell<FileSystemNode>>>, // size为0时表示这是一个目录 size: usize } impl FileSystemNode { pub fn new() -> FileSystemNode { return FileSystemNode { current_directory_path: String::from(""), current_directory_name: String::from(""), parent_directory: None, children: Vec::new(), size: 0 }; } } pub fn main(){ let root = Rc::new(RefCell::new(FileSystemNode::new())); root.borrow_mut().current_directory_path = String::from("/"); let node = Rc::new(RefCell::new(FileSystemNode::new())); node.borrow_mut().current_directory_path = String::from("/test/"); node.borrow_mut().current_directory_name = String::from("test"); node.borrow_mut().parent_directory = Some(Rc::clone(&root)); root.borrow_mut().children.push(Rc::clone(&node)); println!(""); }
.gdbinit配置
import sys sys.path.insert(0, "/path/to/FileSystemNodePrettyPrinterParent") from FileSystemNodePrettyPrinter import register_printer register_printer(None) end layout next
完整FileSystemPrettyPrinter.py代码
# 临时简易美化打印机,用于解决无限递归问题 import gdb class FileSystemNodePrinter: def __init__(self, val): self.val = val def to_string(self): return 'test' def display_hint(self): return 'FileSystemNode' def register_printer(objfile): if objfile == None: objfile = gdb.current_objfile() gdb.printing.register_pretty_printer(objfile, build_pretty_printer(), True) print("Registered pretty printers for UE classes") def build_pretty_printer(): pp = gdb.printing.RegexpCollectionPrettyPrinter("Custom") pp.add_printer("FileSystemNode", '^FileSystemNode$', FileSystemNodePrinter) return pp register_printer(None)
配置好.gdbinit中的路径后启动程序,在root初始化完成后执行打印操作即可复现问题。
内容的提问来源于stack exchange,提问作者Tare
相关产品推荐
相关产品推荐

