为含trait对象的Post结构体实现Debug trait时栈溢出如何解决?
解决包含 trait 对象的
Post结构体Debug实现栈溢出问题 问题根源
你的代码中dyn State的Debug和Display实现陷入了无限递归:
Debug的fmt方法里调用write!(f, "{}", self),会触发Display的fmt方法执行- 而
Display的fmt方法又再次调用write!(f, "{}", self),循环往复直到栈被撑爆,最终抛出栈溢出错误
解决方案
下面提供几种可行的修复方式,根据你的实际需求选择:
方案1:给State trait添加Debug约束
让每个实现State的具体类型自行实现Debug,dyn State会自动继承该约束并调用具体类型的Debug实现:
use std::fmt::{Debug, Display, Formatter, Result as fmtResult}; #[derive(Debug)] pub struct Post { state: Option<Box<dyn State>>, content: String, } // 给State trait添加Debug约束 trait State: Debug { fn request_review(self: Box<Self>) -> Box<dyn State>; fn approve(self: Box<Self>) -> Box<dyn State>; fn content<'a>(&self, post: &'a Post) -> &'a str { "" } } // 移除原来的impl Debug for dyn State和impl Display for dyn State
方案2:手动实现非递归的Debug/Display输出
如果不想给State加Debug约束,可以直接在dyn State的实现里输出有意义的非递归内容,比如内存地址或固定标识:
use std::fmt::{Debug, Display, Formatter, Result as fmtResult}; #[derive(Debug)] pub struct Post { state: Option<Box<dyn State>>, content: String, } trait State { fn request_review(self: Box<Self>) -> Box<dyn State>; fn approve(self: Box<Self>) -> Box<dyn State>; fn content<'a>(&self, post: &'a Post) -> &'a str { "" } } impl Debug for dyn State { fn fmt(&self, f: &mut Formatter<'_>) -> fmtResult { // 输出对象的内存地址,避免递归 write!(f, "StateObject({:p})", self) } } impl Display for dyn State { fn fmt(&self, f: &mut Formatter<'_>) -> fmtResult { write!(f, "StateObject({:p})", self) } }
方案3:给State添加自定义格式化方法
如果需要每个State实现都有专属的Display输出,可以给trait新增格式化方法,避免递归调用:
use std::fmt::{Debug, Display, Formatter, Result as fmtResult}; #[derive(Debug)] pub struct Post { state: Option<Box<dyn State>>, content: String, } trait State { fn request_review(self: Box<Self>) -> Box<dyn State>; fn approve(self: Box<Self>) -> Box<dyn State>; fn content<'a>(&self, post: &'a Post) -> &'a str { "" } // 新增自定义格式化方法 fn fmt_display(&self, f: &mut Formatter<'_>) -> fmtResult; } impl Display for dyn State { fn fmt(&self, f: &mut Formatter<'_>) -> fmtResult { self.fmt_display(f) } } impl Debug for dyn State { fn fmt(&self, f: &mut Formatter<'_>) -> fmtResult { write!(f, "State({})", self) } } // 以具体实现为例: struct Draft; impl State for Draft { fn request_review(self: Box<Self>) -> Box<dyn State> { Box::new(PendingReview) } fn approve(self: Box<Self>) -> Box<dyn State> { self } fn fmt_display(&self, f: &mut Formatter<'_>) -> fmtResult { write!(f, "Draft") } } struct PendingReview; impl State for PendingReview { fn request_review(self: Box<Self>) -> Box<dyn State> { self } fn approve(self: Box<Self>) -> Box<dyn State> { Box::new(Published) } fn fmt_display(&self, f: &mut Formatter<'_>) -> fmtResult { write!(f, "PendingReview") } } struct Published; impl State for Published { fn request_review(self: Box<Self>) -> Box<dyn State> { self } fn approve(self: Box<Self>) -> Box<dyn State> { self } fn content<'a>(&self, post: &'a Post) -> &'a str { &post.content } fn fmt_display(&self, f: &mut Formatter<'_>) -> fmtResult { write!(f, "Published") } }
内容的提问来源于stack exchange,提问作者dNyrM
相关产品推荐
相关产品推荐

