【问题标题】:How can I do I/O in @safe functions in D?如何在 D 中的 @safe 函数中执行 I/O?
【发布时间】:2013-09-30 18:34:19
【问题描述】:

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

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

【问题讨论】:

    标签: d


    【解决方案1】:

    你没有,或者至少没有直接。 I/O 需要进行系统调用,这意味着 C 函数,而 C 函数不会是 @safe。而且由于writeln 目前在后台调用printf,它肯定不会是@safe,因为用printf 做不安全的事情是微不足道的(比如给它@987654326 @ 然后传递一个整数而不是字符串)。在某些情况下可能可以创建writeln @trusted,但我不知道这会涉及什么。这将取决于它的实施方式。

    任何重要的 D 程序都将使用@system 代码,这是完全可以预料的。诀窍是隔离它。你的程序的大部分希望是@safe,但它的部分必须是@system。但是,您只需检查程序的一小部分以确保内存安全。一旦您手动验证调用@system 函数的函数实际上是内存安全的,您可以将其标记为@trusted,然后您可以在@safe 代码中使用它。

    不幸的是,druntime 和 Phobos 中的某些核心内容很可能是 @system,这取决于它对低级内容所做的事情,并且不一定所有这些内容都标有 @trusted,因为它应该是(例如,std.array.appender 可能是 @system,而它应该可以是 @trusted - 我不确定它目前是什么;它可能取决于数组的元素类型)。所以,很可能需要对一些标准库的东西进行一些改进,以便更好地支持@safe(正在进行中,但我不知道现在所有这些都在哪里),你可能会结束现在不得不在比将来更多的地方使用@trustedwriteln 将来可能会也可能不会成为@safe@trusted。但是,如果您使用的类型没有 @safe@trusted toString 函数,则绝对不会,所以writeln 是否是@safe 的一部分取决于你是什么使用它,不管它是如何实现的。但是,即使使用内置类型,它目前也不是 @safe@trusted,所以现在,你运气不好。

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

    【讨论】:

    • 这很有意义 - 尤其是对于大多数代码(除了实际的低级函数),可以避免内存安全 IMO(指针)中最严重的违规者。
    • @Demetri 没错。您的程序中有@system 代码,但它是孤立的,而且它通常是一个足够小的部分,可以自己验证它的内存安全性是合理的,而如果您根本没有@safe,则必须自己验证整个程序,这显然要困难得多。
    • writefln 肯定可以设置为@安全的,除了 char* 的自动打印,因为可能没有零终止符(实际上是这样吗?或者它只是将指针显示为十六进制?)它根本没有必须使用 printf - 我们已经有 std.format.formattedWrite 可以完成大部分工作,那么对 C 的最终调用也可能会得到验证或类似 fwrite () 这是相当理智的。至少肯定是@受信任的。
    • @AdamD.Ruppe 我希望writeln 可能是安全的,只要参数具有适当的@safe 功能(例如@safetoString),但它可以'不能简单地标记为@trusted@safe,而且我不知道在不标记不应该是@trusted 的部分@trusted 的情况下标记适当的部分@trusted 是多么容易。因此,根据实施情况,这可能会有点痛苦。我希望我们能到达那里。
    【解决方案2】:

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

    【讨论】:

    • 你不能对自定义类的 to!string 调用可能不是 @safe
    • 但这并不一定是一个破坏者,因为这只发生在某些模板参数上。我认为属性推断会抓住这些情况。
    • 能够在 SafeD 中编写整个程序可能非常棒
    猜你喜欢
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 2015-05-09
    • 2012-03-01
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    相关资源
    最近更新 更多