我正在学习 D 编程语言,并且我试图将自己限制在它的 SafeD 子集中。但是,我注意到像 writeln 这样的 I/O 函数都是@system。我如何在 SafeD 中进行 I/O?
我在 Fedora 19 x86-64 上使用 LDC2(从 Fedora 包下载)。
最佳答案
你没有,或者至少不是直接的。 I/O 需要进行系统调用,这意味着 C 函数,而 C 函数不会是 @safe
.自从writeln
目前调用printf
在引擎盖下,它绝对不会是 @safe
, 因为用 printf
做不安全的事情是微不足道的(比如给它%s
,然后给它一个整数而不是一个字符串)。有可能使writeln
@trusted
在某些情况下,但我不知道这会涉及什么。这将取决于它是如何实现的。
任何非平凡的 D 程序都将使用 @system
代码。诀窍是隔离它。您的程序的大部分内容有望是 @safe
, 但它的部分必须是 @system
.但是,您只需检查程序的一小部分以确保内存安全。一旦您手动验证调用 @system
的函数函数实际上是内存安全的,您可以将其标记为 @trusted
然后你可以在 @safe
中使用它代码。
不幸的是,druntime 和 Phobos 中的某些核心内容也很可能是 @system
。基于它对低级东西所做的事情,不一定所有这些都被标记为 @trusted
应该是这样(例如 std.array.appender
可能是 @system
而它可能应该是 @trusted
- 我不确定它目前是什么;它可能取决于数组的元素类型)。所以,为了更好地支持 @safe
,可能需要对一些标准库的东西进行一些改进。 (正在进行中,但我不知道现在所有这些都在哪里),您最终可能不得不使用 @trusted
现在在比你将来更多的地方。 writeln
可能是也可能不是@safe
或 @trusted
在将来。但是,如果您使用的类型没有 @safe
,则绝对不会。或 @trusted
toString
功能,所以部分是否 writeln
是 @safe
取决于您使用它的方式,无论它是如何实现的。但是,目前不是 @safe
或 @trusted
即使使用内置类型,所以现在,你不走运。
如果你真的想要,你可以为 writeln
创建一个包装器。这是@trusted
,但是您必须非常小心,以确保代码实际上是内存安全的 - 并且只需创建一个模板包装器并将其标记为 @trusted
不会削减它,因为那样你就会把它当作 @safe
不管你传递给它什么类型。因此,最好不要包装它,然后将调用者标记为 @trusted
如果您确定 writeln
的特殊用途是内存安全的。当然,这也突出了为什么像 writeln
这样的函数的部分原因。目前是 @system
首先:通常很难写@trusted
模板化代码不信任不应信任的东西(因为它取决于模板参数)。属性推断通常会解决这个问题,但如果模板代码正在做一些需要 @trusted
的事情, 将代码的一部分标记为 @trusted
变得很困难剩下的留给推理,尤其是当模板参数与 @system
混合在一起时东西。不过,我希望我们最终会对所有标准库的内容进行整理。
关于d - 如何在 D 中的 @safe 函数中执行 I/O?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19101305/