8

我正在学习 D 编程语言,并且我试图将自己限制在它的 SafeD 子集中。但是,我注意到像 writeln 这样的 I/O 函数都是@system。我如何在 SafeD 中进行 I/O?

我在 Fedora 19 x86-64 上使用 LDC2(从 Fedora 包下载)。

4

2 回答 2

10

你没有,或者至少不是直接的。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东西混合在一起. 不过,我希望我们最终会对所有标准库的内容进行整理。

于 2013-09-30T19:17:25.183 回答
5

我认为我们应该让 writeln 和朋友成为朋友@trusted——尽管他们使用低级原语,但他们进行了足够的检查以确保例如 printf 没有收到混乱的参数。

于 2013-09-30T20:12:39.853 回答