Rust 什么时候将特征标记为不安全,而不是将特征中的所有功能标记为不安全?
在代码中说同样的话,我什么时候会选择下面的例子Rust 什么时候将特征标记为不安全,而不是将特征中的所有功能标记为不安全?,rust,traits,Rust,Traits,在代码中说同样的话,我什么时候会选择下面的例子 unsafe trait MyCoolTrait { fn method(&self) -> u8; } trait MyCoolTrait { unsafe fn method(&self) -> u8; } 各国: 不安全特性是一种不安全的特性,因为它表示某种可信的断言。请注意,使用不安全特性是完全安全的。和Share(注意:现在称为)是不安全特性的示例:实现这些特性实际上是断言您的类型对于线程是
unsafe trait MyCoolTrait {
fn method(&self) -> u8;
}
trait MyCoolTrait {
unsafe fn method(&self) -> u8;
}
各国:
不安全特性是一种不安全的特性,因为它表示某种可信的断言。请注意,使用不安全特性是完全安全的。和Share
(注意:现在称为)是不安全特性的示例:实现这些特性实际上是断言您的类型对于线程是安全的
标准库中还有另一个不安全特征的例子。它说:
该特性被标记为不安全,因为next()
方法返回的索引必须位于haystack中的有效utf8边界上。这使得这种特性的消费者能够在不进行额外的运行时检查的情况下对干草堆进行切片
不幸的是,这些段落都没有真正帮助我理解什么时候标记整个特征而不是部分或全部方法是正确的
之前,但这似乎有所不同。一个函数被标记为
不安全
,表示调用它可能会违反内存安全。一个特征被标记为不安全
,表示通过实现它可能会违反内存安全。这通常是因为特征具有其他不安全代码所依赖的不变量,并且这些不变量不能以任何其他方式表示
对于Searcher
,调用方法本身应该是安全的。也就是说,用户不必担心他们是否正确使用了搜索器
;接口合同规定所有调用都是安全的。您不能做任何会导致这些方法违反内存安全性的事情
但是,不安全代码将调用搜索器
的方法,并且此类不安全代码将依赖给定的搜索器
实现返回有效UTF-8代码点边界上的偏移量。如果违反了此假设,则不安全代码可能最终导致内存安全冲突
换句话说:使用Searcher
s的不安全代码的正确性取决于每个Searcher
实现是否正确。或者:不正确地实现此特性会导致安全代码导致内存安全冲突,这与不安全代码无关
那么,为什么不将方法标记为不安全的呢?因为它们一点都不安全!他们不会做任何可能破坏自身记忆安全的事情next\u match
只需扫描并返回一个选项
。只有当不安全代码假定这些usize
s是搜索字符串的有效索引时,才存在危险
那么为什么不检查一下结果呢?因为那样会慢一些。搜索代码要快,这意味着它要避免冗余检查。但是这些检查不能在搜索器界面中表达。。。因此,整个特征被标记为不安全
,以警告实现它的任何人,代码中没有说明或强制执行的额外条件必须得到遵守
还有Send
和Sync
:当您不应该违反必须处理线程的代码的期望时,实现它们。允许您创建线程的代码是安全的,但前提是Send
和Sync
仅在适当的类型上实现。经验法则如下:
- 如果方法用户需要在
unsafe
块中包装方法调用,请使用unsafe fn method()
- 如果特质实施者需要
unsafe impl MyTrait
,请使用unsafe trait MyTrait
unsafe
是提醒用户:不安全的代码必须小心编写。
关键的一点是,unsafe
应该作为双重标准使用:当作者将一个特征/功能声明为unsafe时,实现者/用户需要将其与unsafe
一起实现/使用
当功能被标记为不安全时,表示用户需要小心使用该功能。函数作者假设函数用户必须保留
当trait被标记为不安全时,意味着trait实现者需要小心地实现。这种特性要求实现者保持一定的假设。但是不安全特性的用户可以随意调用特性中定义的方法
例如,unsafe trait Searcher
要求所有Searcher
实现在调用next
时应返回有效的utf8边界。并且所有实现都标记为不安全的impl Searcher
,表示实现代码可能不安全。但是作为Searcher
的用户,可以调用Searcher.next()
,而无需将其包装在unsafe
块中。不确定如何将其转换为一个好的答案b/c这对我来说似乎是显而易见的。不安全特征只用于安全代码。当您希望实现者在实现某个特性时给予额外注意时,您将该特性标记为不安全,因为很容易出错,而且基本上保证任何实现者都需要不安全的代码来实现该特性。@kerSend
和Sync
甚至没有实现者可能需要的任何方法unsafe
,而Searcher
的方法对我来说似乎也不安全。而且不安全
从来都不是关于“容易出错”,只是关于内存安全。发送和同步是标记特征。我不认为这个问题是关于标记特征的。不安全总是关于“容易出错”(+导致内存不安全)。如果实现者必须键入“不安全”,他知道他可能会导致内存不安全