我正在学习 D 编程语言,并且我试图将自己限制在它的 SafeD 子集中。但是,我注意到像 writeln 这样的 I/O 函数都是@system。我如何在 SafeD 中进行 I/O?
我在 Fedora 19 x86-64 上使用 LDC2(从 Fedora 包下载)。
我正在学习 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
东西混合在一起. 不过,我希望我们最终会对所有标准库的内容进行整理。
我认为我们应该让 writeln 和朋友成为朋友@trusted
——尽管他们使用低级原语,但他们进行了足够的检查以确保例如 printf 没有收到混乱的参数。