.. _unsafe: ====== Unsafe ====== .. index:: single: Unsafe ``unsafe`` 关键字表示不安全的内容,这是作所必需的,但可能会使应用程序崩溃:: unsafe { let px = addr(x) } 表达式(和子表达式)也可能是不安全的:: let px = unsafe(addr(x)) Unsafe 后跟一个可以包含这些作的块。允许嵌套的 unsafe 部分。在 lambda、generator 或本地函数中不会继承 Unsafe;但是,它是在本地块中继承的。 单个表达式可能会导致 `CompilationError::unsafe` 错误,除非它们是 unsafe 部分的一部分。此外,宏可以显式设置 `ExprGenFlags::alwaysSafe` 标志。 表达式的地址不安全:: unsafe { let a : int let pa = addr(a) return pa // 访问 *PA 可能会损坏堆栈 } lambda 或生成器需要不安全的部分才能通过 move 或 by reference 进行隐式捕获:: var a : array unsafe { var counter <- @ (extra:int) : int { return a[0] + extra // a 被隐式移动 } } 删除任何指针都需要一个 unsafe 部分:: var p = new Foo() var q = p unsafe { delete p // 访问 q 可能会损坏内存 } Upcast 和 reinterpret cast 需要一个 unsafe 部分:: unsafe { return reinterpret 13 // reinterpret 可以创建不安全的指针 } 索引到指针中是不安全的:: unsafe { var p = new Foo() return p[13] // 访问越界指针可能会损坏内存 } 如果 safe 索引后面没有 null 合并运算符,则 safe 索引是不安全的:: var a = { 13 => 12 } unsafe { var t = a?[13] ?? 1234 // safe return a?[13] // unsafe; safe Index 是 'addr'作的一种形式 // 它可以创建指向临时对象的指针 } 如果 null 合并运算符后跟,则局部变量上的变体 ``?as`` 是不安全的:: unsafe { return a ?as Bar // 安全,就像 'addr'作的一种形式一样 } 变体 ``.?field`` 当后面没有 null 合并运算符时是不安全的:: unsafe { return a?.Bar // 变体的安全导航是 'addr'作的一种形式 } 变体 ``.field`` 是 unsafe:: unsafe { return a.Bar // 这可能是 reinterpret cast(重新解释的演员阵容) } 某些函数和运算符本质上是不安全的,或者通过 [unsafe_operation] 注释标记为不安全:: unsafe { var a : int? a += 13 // 指针算术可以创建无效指针 var boo : int[13] var it = each(boo) // 数组的 each() 是不安全的,因为它不会捕获 } 从智能指针值移动需要 unsafe,除非该值是 'new' 运算符:: unsafe { var a <- new TestObjectSmart() // safe, 它显然是新的 var b <- someSmartFunction() // unsafe 由于寿命不明显 b <- a // safe, 值不会丢失 } 移动或复制类是不安全的:: def foo ( var b : TestClass ) { unsafe { var a : TestClass a <- b // 可能从派生类移动 } } 局部类变量不安全:: unsafe { var g = Goo() // 潜在的生命周期问题 } ======== implicit ======== `implicit` 关键字用于指定 type 可以是 临时 或 常规 类型,并将被视为已定义。 例如:: def foo ( a : Foo implicit ) // a 将被视为 Foo,但也接受 Foo# 作为参数 def foo ( a : Foo# implicit ) // a 将被视为 Foo#,但也接受 Foo 作为参数 不幸的是,像这样的隐式转换是不安全的,因此 `implicit` 根据定义是不安全的。 =========== 其他情况 =========== 还有其他几种情况需要 `unsafe`,但文档中没有明确提到。 它们通常通过 CodeOfPolicies 或适当的选项进行控制:: options unsafe_table_lookup = false // 使表索引安全。见 CodeOfPolicies::unsafe_table_lookup var tab <- { 1=>"one", 2=>"two" } tab[3] = "three" // 这是不安全的,因为它可以创建指向临时对象的指针