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

Dem*_*emi 8 d

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

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

Jon*_*vis 8

你没有,或者至少没有直接.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内容混合的情况下.我希望我们最终会对所有标准库的东西进行排序.

  • 这很有意义 - 尤其是作为内存安全中最糟糕的罪犯,无论如何都可以避免IMO(指针)(除了实际的低级别功能). (2认同)
  • @Demetri完全正确.你的程序中有`@ system`代码,但它是孤立的,它通常是一个足够小的部分,你自己验证它的内存安全是合理的,而如果你根本没有`@ safe`,你会必须自己验证你的整个程序,这显然要困难得多. (2认同)
  • @ AdamD.Ruppe我希望`writeln`可能只要参数具有适当的`@ safe`功能(例如`@ safe``toString`)就可以安全,但它不能简单地标记为` @ trusted`或`@ safe`,我不知道标记相应部分`@ trusted`而不标记不应该是`@ trusted`的部分`@ trusted`是多么容易.因此,根据实施情况,可能会有点痛苦.我希望我们能够到达那里. (2认同)

And*_*scu 5

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