如何在D中的@safe函数中执行I / O操作?

时间:2013-09-30 18:34:20

标签: d

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

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

2 个答案:

答案 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将来可能会或可能不会@trustedwriteln。但是,如果您使用它的类型没有@safe@trusted @safe函数,那肯定不会,那么@trustedtoString的一部分{1}}取决于您使用它的内容,无论其实现方式如何。但是,即使使用内置类型,它目前也不是writeln@safe,所以现在,你运气不好。

如果您真的想要,可以为@safe @trusted创建一个包装器,但是您必须非常小心,以确保代码实际上是内存安全的 - 并且只是创建一个模板化的包装并标记它writeln不会削减它,因为那样你将它视为@trusted而不管你传递给它的类型。因此,如果您确定@trusted的特定用途是内存安全的话,最好不要将其包装然后将调用者标记为@safe。当然,这也首先突出了@trusted这样的函数当前writeln的部分原因:通常很难编写writeln模板化代码而不信任不应该信任的东西(因为它取决于模板参数)。属性推断通常会解决问题,但如果模板化代码正在执行需要@system的操作,则很难将代码的一部分标记为@trusted,并将其余部分留给推理,尤其是如果模板参数与@trusted内容混合在一起。我希望我们最终会对所有标准库的内容进行整理。

答案 1 :(得分:5)

我认为我们应该让writeln和朋友@trusted - 虽然他们使用低级原语,但他们做了足够的检查以确保例如printf没有收到搞砸的论据。