对于只有一小部分代码实际上在做“不安全”事情的“不安全”函数,最佳实践是什么?
What are best practices for `unsafe` functions in which only a small part of the code is actually doing `unsafe` things?
在我正在开发的 crate 中,我有几个 unsafe
函数,由于 的原因,它们被标记为这样。在 unsafe
函数中,我可以执行 unsafe
操作,就好像完整的函数体被包裹在 unsafe { }
块中一样。
问题在于,在较大的函数中,只有一小部分函数体实际上在执行 unsafe
操作,而其余部分则在做完全安全的事情。通常,这种安全的东西甚至完全独立于 unsafe
代码。在这些较大的函数中,我想缩小unsafe
操作的范围。原因应该很容易理解:我也不会仅仅因为可以就将我的完整代码库包装在 unsafe { }
块中。
不幸的是,unsafe
函数的行为 "invert" 没有 safe { }
块。如果有我会这样使用它:
unsafe fn my_function() {
safe {
// ... doing safe stuff ...
unsafe {
// ... doing `unsafe` stuff ...
}
// ... doing safe stuff ...
}
}
但这是不可能的:在这些情况下缩小 unsafe
操作范围的最佳做法是什么?是否有解决此问题的既定技巧?
明确一点:这个问题不是讨论缩小unsafe
范围是好是坏。我说我想做:这个问题是关于 如何 做以及什么解决方案(如果有的话)最常在实践中使用 . (如果你不明白我为什么要这样做,this RFC 是非常相关的。)
如果您想使用 unsafe
关键字来对所有不安全的操作进行分类,您可以通过将代码拆分为安全的私有函数来构造更准确的边界。我不确定它是否完全满足您 "best practice" 的要求,因为我不知道有任何大型项目使用该技术,但它会起作用:
// 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 ...
}
如果您担心 "safe" 函数的存在实际上是不安全的,引入了意外被错误使用的风险,您可以嵌套这些私有函数,这样它们就不能在主函数之外调用不安全函数:
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();
}
毕竟,正确记录不安全代码的假设和注释是最重要的部分。这种技巧只有在您关注不安全行数的指标时才有用。
在我正在开发的 crate 中,我有几个 unsafe
函数,由于 unsafe
函数中,我可以执行 unsafe
操作,就好像完整的函数体被包裹在 unsafe { }
块中一样。
问题在于,在较大的函数中,只有一小部分函数体实际上在执行 unsafe
操作,而其余部分则在做完全安全的事情。通常,这种安全的东西甚至完全独立于 unsafe
代码。在这些较大的函数中,我想缩小unsafe
操作的范围。原因应该很容易理解:我也不会仅仅因为可以就将我的完整代码库包装在 unsafe { }
块中。
不幸的是,unsafe
函数的行为 "invert" 没有 safe { }
块。如果有我会这样使用它:
unsafe fn my_function() {
safe {
// ... doing safe stuff ...
unsafe {
// ... doing `unsafe` stuff ...
}
// ... doing safe stuff ...
}
}
但这是不可能的:在这些情况下缩小 unsafe
操作范围的最佳做法是什么?是否有解决此问题的既定技巧?
明确一点:这个问题不是讨论缩小unsafe
范围是好是坏。我说我想做:这个问题是关于 如何 做以及什么解决方案(如果有的话)最常在实践中使用 . (如果你不明白我为什么要这样做,this RFC 是非常相关的。)
如果您想使用 unsafe
关键字来对所有不安全的操作进行分类,您可以通过将代码拆分为安全的私有函数来构造更准确的边界。我不确定它是否完全满足您 "best practice" 的要求,因为我不知道有任何大型项目使用该技术,但它会起作用:
// 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 ...
}
如果您担心 "safe" 函数的存在实际上是不安全的,引入了意外被错误使用的风险,您可以嵌套这些私有函数,这样它们就不能在主函数之外调用不安全函数:
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();
}
毕竟,正确记录不安全代码的假设和注释是最重要的部分。这种技巧只有在您关注不安全行数的指标时才有用。