在我正在开发的板条箱中,我有几个
unsafe
功能,由于在这个答案中解释的原因,这些功能被标记为这样。在 unsafe
函数中,我可以执行 unsafe
操作,就好像完整的函数体被包装在 unsafe { }
块中一样。
问题在于,在较大的函数中,函数体中只有一小部分实际上在执行
unsafe
操作,而其余部分则在执行完全安全的操作。通常,这种安全的东西甚至非常独立于 unsafe
代码。在这些较大的函数中,我想缩小unsafe
操作的范围。原因应该是可以理解的:我也不会仅仅因为可以将完整的代码库包装在 unsafe { }
块中。
不幸的是,没有一个
safe { }
块可以“反转” unsafe
函数的行为。如果有的话我会这样使用它:
unsafe fn my_function() {
safe {
// ... doing safe stuff ...
unsafe {
// ... doing `unsafe` stuff ...
}
// ... doing safe stuff ...
}
}
但是这是不可能的:在这些情况下缩小
unsafe
操作范围的最佳实践是什么?有没有既定的技巧来处理这个问题?
需要明确的是:这个问题不是讨论缩小
unsafe
范围是好是坏。我说过我想这样做:这个问题是关于“如何”去做以及“在实践中最常用”什么解决方案(如果有)。 (如果您不明白我为什么要这样做,这个 RFC 非常相关。)
如果您想使用 unsafe
// Document the assumptions of this unsafe function here
pub unsafe fn my_function() {
my_internal_function()
}
// private
fn my_internal_function() {
// ... doing safe stuff ...
unsafe {
// Document the assumptions of this unsafe block here
// ... doing `unsafe` stuff ...
}
// ... doing safe stuff ...
}
如果您担心存在实际上不安全使用的“安全”函数,从而引入意外错误使用的风险,您可以嵌套这些私有函数,这样它们就无法在主不安全函数之外调用:
pub unsafe fn my_function() {
fn my_internal_function() {
// ... doing safe stuff ...
unsafe {
// Document the assumptions of this unsafe block here
// ... doing `unsafe` stuff ...
}
// ... doing safe stuff ...
}
my_internal_function();
}
完成所有这些之后,用注释正确记录不安全代码的假设是最重要的部分。仅当您担心不安全线路数量的指标时,这种技巧才会有帮助。
对于未来阅读此问题的人,现在我们对此有一个 lint(您可以通过关注
此问题#![deny(unsafe_op_in_unsafe_fn)]
,则在 unsafe fn
中使用不安全操作时会出现错误,除非您在其周围添加
unsafe
块。 (即,在OP的语言中,实际上有一个safe
块包裹着所有unsafe fn
的主体。)