Rust中能否将分配为Full<T>的内存以Header类型执行drop?
Rust跨类型指针释放内存的可行性分析
核心结论
你代码里的操作完全不可行,会触发未定义行为,哪怕<T>没有自定义Drop实现也一样。
为什么和C的free不一样?
C的free只认分配时的内存起始地址,分配器会自行记录内存块的大小,所以只要指针是分配时的起始地址,不管类型是什么都能释放。但Rust的Box::from_raw不是单纯的内存释放:
- 它会先调用指针对应类型的
Drop析构函数(哪怕是默认生成的); - 它会告诉分配器释放该类型大小的内存块——这里的类型必须和分配时的类型严格匹配,否则分配器的内存管理记录会被破坏,直接导致未定义行为(比如内存损坏、后续分配崩溃)。
你的代码具体问题在哪?
你用Box::new(Full<&'static str>)分配了一块size_of::<Full<&str>>()大小的内存,然后把指针强转成*mut Header。当你用Box::from_raw(ptr_s)释放时:
- 程序会认为要释放的是
Header类型的内存,只告诉分配器释放size_of::<Header>()字节; - 这就导致
Full<T>里_body部分的内存完全没被正确回收,不仅造成内存泄漏,还会让分配器的内部状态混乱,后续任何内存操作都可能出问题。
满足需求的正确做法
如果要把不同<T>的Full<T>放到同一个容器里,别用原始指针强转的方式,推荐两种靠谱方案:
- Trait Object:定义一个 trait(比如
FullContainer),让Full<T>实现这个 trait,然后用Vec<Box<dyn FullContainer>>来存储,释放时直接drop Box即可,Rust会自动处理类型析构。 - 带类型标记的原始指针:在
Header里加一个类型标识(比如枚举TypeTag),存储时记录每个指针对应的实际类型,释放时根据类型标识把*mut Header转回*mut Full<T>,再用Box::from_raw释放。
内容的提问来源于stack exchange,提问作者wub
相关产品推荐
相关产品推荐

