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