代码之家  ›  专栏  ›  技术社区  ›  porton

std.string.toStringz如何在dlang中工作?

  •  0
  • porton  · 技术社区  · 6 年前

    https://dlang.org/library/std/string/to_stringz.html

    据我所知,这是行不通的:

    toStringz 在堆栈上创建数组并返回其指针。后 托斯特林兹 返回,堆栈上的数组将被丢弃,指针将变为无效。

    但我认为它确实有效,因为它是标准库的一部分。那么,我对上述内容的理解有什么问题呢?

    另一个相关问题:

    什么? scope return 在这个函数的签名中意味着?我参观过 https://dlang.org/spec/function.html 但没有发现 范围返回 那里。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Adam D. Ruppe    6 年前

    它不会在堆栈上创建数组。如果需要,它会在GC堆上分配一个新的字符串。

    该实现通过检查零终止符的现有字符串来工作——如果它认为可以在没有内存错误的情况下这样做(通过检查最后一个字节的对齐来猜测)。如果是4的倍数,它不会冒风险,但是如果不是,它会在指针前面读取一个字节,因为故障边界位于4个间隔的倍数上)。

    如果已经有一个零字节,则返回未修改的输入。就是这样 return 签名中的内容意味着-它可能返回相同的输入。(这是一个新功能,刚刚被记录下来…昨天。它甚至还没有被合并: https://github.com/dlang/dlang.org/pull/2536 但是stdlib文档是从主分支lol重新构建的)

    无论如何,如果那里没有零字节,它将分配一个新的gc'd字符串,复制现有的字符串,附加零,并返回该字符串。这就是文档中的注释警告保存它的C函数的原因。如果C函数使它超出执行范围,那么将获得它的不是堆栈,而是D垃圾收集器。D的GC看不到由C函数分配的内存(除非特别通知它),并且会认为字符串在下次运行时没有被引用,从而释放它,导致在释放bug之后使用。

    这个 scope 签名中的关键字是d检查此btw的方法:它意味着参数将仅用于此函数的作用域(尽管 返回 意味着它将仅用于此函数的作用域或通过此函数返回)。但这是ToStringz的输入——您调用的C函数可能不使用该D语言限制,并且不会自动捕获它。

    因此,要再次总结这些属性:

    范围 -参数不会离开函数的作用域。不会分配给全局或外部结构等。

    返回 -参数可能由函数返回。

    return scope -上面的混合;它不会离开函数的作用域,除非通过返回值。