Rust死灵书中有个例子
struct Vec { data: *const T, // *const 是可变异的! len: usize, cap: usize, }
关于这个例子存在不健壮性,解释说明是这样的: https://nomicon.purewhite.io/phantom-data.html
丢弃检查器将慷慨地确定Vec不拥有任何 T 类型的值。这将反过来使它得出结论,它不需要担心 Vec 在其析构器中丢弃任何 T 来确定丢弃检查的合理性。这将反过来允许人们使用 Vec 的析构器来制造不健壮性。
可否有大神举个例子,上面的代码如何在Vec的析构器中制造不健壮性?
1
共 4 条评论, 1 页
评论区
写评论刚看了下英文,感觉有些理解了, 中文居然漏了很多东西
--
👇
苦瓜小仔:
我十分建议你重新看英文原文,因为
一些词语翻译得并不准确
如果你已经知道这里翻译的“变异”不是“可变”而是“子类型的组织规则”,忽略下述内容。
variance 应为“型变”而不是“变异”,当然重要的不是中文,而是它描述的东西 —— 这在这本书中有专门的一篇。首先要理解“子类型”,然后是“型变”(我从那章摘抄的关键):
子类型/型变主要发生在生命周期上。
而“变异”让人联想起“可变性”(mutability,就是变量的改变)。
阅读翻译的方式应该是中文为辅、英文为主
Rust 真正的官方材料就那么些,如果你真的想知道这些细节,至少要明白每句话大概在说什么,尤其是原文在说什么。只看中文是远远不够的。对我来说,像什么“丢弃”啊、“幽灵数据”啊,是理解障碍,增加记忆负担,人家就叫 drop/Drop 和 PhantomData —— 你会把 Vec 翻译成“向量”(vector) 去理解吗?我独自翻译的 Rust 开源书籍少说也有四本了,所以作为翻译者能理解有时候避免不了为了中文表词达意,把自己觉得很好理解的东西在专有名词上翻译地蹩脚。
可以回答你的问题了:
这篇翻译遗漏了一些内容(可能因为作者问题,也可能因为原文更新问题):
没有翻译原文折叠的部分,那里描述了你想知道的“不健壮性”的具体例子,但主要讲了
#[may_dangle]
的用法。struct Vec { data: *const T, len: usize, cap: usize, }
这个例子还有后半部分:所以,这是一个不需要 PhantomData 的反例!
我总结一下这两部分吧:在手动实现 Drop 中,PhantomData 不再必要,因为它对 drop 没有影响,反而可能会考虑 #[may_dangle]。
然后综合全文:PhantomData 的一个重要应用是描述型变。
@eweca-d 你的时间线不太对。
那部分内容与 drop check 有关,而且基于标准库中的
Vec<T>
来举例,重新整理一下应该是:过去在
Vec<T>
中PhantomData<T>
的原因是让 drop checker 知道在 dropVec<T>
时应该 dropT
PhantomData<T>
会导致 drop check unsoundness现在考虑 drop check 时无需使用
PhantomData<T>
这是由 RFC 1238 带来的。
因为现在
impl<T> Drop for Vec<T>
会考虑在 Drop 实现中考虑 dropT
。实际上现在的
Vec<T>
使用了PhantomData<T>
和#[may_dangle]
#[may_dangle]
需要 unsafe impl,目的是允许显然,
#[may_dangle]
过于宽松(excessively loose),因为我们真正想要的是:即
impl<'s> Drop for Vec<&'s str>
中让drop(s)
先于 (隐式的?)drop(v)
Drop for Vec<PrintOnDrop<'s>>
drop check 水很深(记录的文档是不是比生命周期还多???),我平时用不到,知道些基本的规则,没怎么关注过。
试了下很复杂,碰上 NLL 未能解决的问题。Hmm。。。
应该是更新问题,我看了下自己的nomicon,没有这部分内容,然后更新了一下(从7月的版本到8月8的版本),这个新内容出现了。
所以看起来是在原先设计情况下,假如
T
有一个生命周期&'a
的情况下,能够保证T
超过生命周期被Drop之后,Vec<T>
也能被Drop?从而避免使用者尝试使用里面的指针(此时是悬垂指针)?新的
may_dangle
啥意思?nomicon说过去的方法太过于严格,意思是在Vec<T>
不含真正含有T
的时候,当T
超过生命周期被Drop,这种情况下不再DropVec<T>
?我十分建议你重新看英文原文,因为
一些词语翻译得并不准确
如果你已经知道这里翻译的“变异”不是“可变”而是“子类型的组织规则”,忽略下述内容。
variance 应为“型变”而不是“变异”,当然重要的不是中文,而是它描述的东西 —— 这在这本书中有专门的一篇。首先要理解“子类型”,然后是“型变”(我从那章摘抄的关键):
子类型/型变主要发生在生命周期上。
而“变异”让人联想起“可变性”(mutability,就是变量的改变)。
阅读翻译的方式应该是中文为辅、英文为主
Rust 真正的官方材料就那么些,如果你真的想知道这些细节,至少要明白每句话大概在说什么,尤其是原文在说什么。只看中文是远远不够的。对我来说,像什么“丢弃”啊、“幽灵数据”啊,是理解障碍,增加记忆负担,人家就叫 drop/Drop 和 PhantomData —— 你会把 Vec 翻译成“向量”(vector) 去理解吗?我独自翻译的 Rust 开源书籍少说也有四本了,所以作为翻译者能理解有时候避免不了为了中文表词达意,把自己觉得很好理解的东西在专有名词上翻译地蹩脚。
可以回答你的问题了:
这篇翻译遗漏了一些内容(可能因为作者问题,也可能因为原文更新问题):
没有翻译原文折叠的部分,那里描述了你想知道的“不健壮性”的具体例子,但主要讲了
#[may_dangle]
的用法。struct Vec { data: *const T, len: usize, cap: usize, }
这个例子还有后半部分:所以,这是一个不需要 PhantomData 的反例!
我总结一下这两部分吧:在手动实现 Drop 中,PhantomData 不再必要,因为它对 drop 没有影响,反而可能会考虑 #[may_dangle]。
然后综合全文:PhantomData 的一个重要应用是描述型变。