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

问题描述 投票:0回答:2

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

在我的理解中它无法工作:

toStringz
在堆栈上创建一个数组并返回它的指针。
toStringz
返回后,栈上数组被丢弃,指针失效

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

另一个相关问题:

函数签名中的

scope return
是什么意思?我访问了https://dlang.org/spec/function.html但没有发现
scope return
那里。

string memory-management d interfacing
2个回答
2
投票

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

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

如果那里已经有一个零字节,它返回未修改的输入。这就是签名中

return
的意思——它可能会返回相同的输入。 (这是一个刚刚记录的新功能......昨天。它甚至还没有合并:https://github.com/dlang/dlang.org/pull/2536但是stdlib文档是从重建的主分支哈哈)

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

签名中的

scope
关键字是D检查这个顺便说一句的方式:这意味着参数将只在这个函数的范围内使用(虽然
return
的组合意味着它只会在这个函数的范围内使用或通过返回这个功能)。但那是在 toStringz 的输入上——你调用的 C 函数可能不使用 D 语言限制,它不会被自动捕获。

所以再总结一下属性:

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

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

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


0
投票

Adam,防止释放后使用错误的推荐方法是什么?

如果您的 D 代码未实现推荐的防护措施,编译器是否可能内置了一些开发功能,从而大声尖叫?或者,更好的是,D 可以在某处自动创建一个指针,引用字符串的副本加上终止 0 吗?

如果 D 编译器将 xchar 的字符串和数组过度分配 1 个字节,再加上出于对齐原因可能多一点,并在结束后的字节中放置一个零,每个人都会生气吗?这样 tostringz 就会变得微不足道,昂贵的内存块复制就会消失,错误就会消失,一切都会与 C 兼容。

© www.soinside.com 2019 - 2024. All rights reserved.