首页 > 解决方案 > How does std.string.toStringz work in dlang?

问题描述

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

In my understanding it could not work:

toStringz creates an array on the stack and returns its pointer. After toStringz returns, the array on the stack is discarded and the pointer becomes invalid.

But I suppose it indeed works because of being a part of the standard library. So what is wrong in my understanding of the above?

Another related question:

What does scope return in the signature of this function mean? I visited https://dlang.org/spec/function.html but found no scope return there.

标签: stringmemory-managementdinterfacing

解决方案


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

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

如果那里已经有一个零字节,它会返回未修改的输入。这就是return签名中的意思——它可能会返回相同的输入。(这是一个刚刚记录的新功能......昨天。它甚至还没有合并:https ://github.com/dlang/dlang.org/pull/2536但是stdlib文档是从master重建的分支大声笑)

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

签名中的scope关键字是 D 检查此 btw 的方式:这意味着参数将仅在此函数的范围内使用(尽管组合return意味着它将仅在此函数的范围内使用或通过此函数返回)。但这是 toStringz 的输入 - 您调用的 C 函数可能不使用 D 语言限制,因此它不会被自动捕获。

所以再次总结属性:

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

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

return scope- 上述的混合体;它不会通过返回值离开函数的范围。


推荐阅读