如何解决CGO 指针检查中的已知实现错误
根据 CGO (https://pkg.go.dev/cmd/cgo) 的文档,在实现中有一个已知的错误:
注意:当前的实现有一个错误。虽然 Go 代码允许将 nil 或 C 指针(但不是 Go 指针)写入 C 内存,但如果 C 内存的内容看起来是 Go 指针,当前实现有时可能会导致运行时错误。因此,如果 Go 代码要在其中存储指针值,请避免将未初始化的 C 内存传递给 Go 代码。在将 C 中的内存传递给 Go 之前将其清零。
我在 GitHub 的问题跟踪器中寻找过这个,但在那里找不到。有人可以详细说明为什么会发生这种情况吗?运行时如何在未初始化的 C 内存中找到 Go 指针?
例如。假设我将一个未初始化的 char 数组从 C 传递给 Go 函数,运行时如何解释该内存中的 Go 指针?
此外,“如果 Go 代码将在其中存储指针值”部分让我感到困惑。为什么以后使用此内存很重要?
解决方法
我在 GitHub 的问题跟踪器中寻找过这个,但在那里找不到。
此评论所指的错误是 https://golang.org/issue/19928,这确实不容易找到。 ?
有人可以详细说明为什么会发生这种情况吗?运行时如何在未初始化的 C 内存中找到 Go 指针?
在垃圾收集周期的某些部分,收集器打开一个“write barrier”,用于写入Go堆中的指针,记录之前存储的指针值,以确保在GC期间不会遗漏扫描。
这里的错误是写屏障有时也会记录先前存储的指针值,用于外部 Go 堆。如果该值看起来像 Go 指针,垃圾收集器可能会尝试递归扫描它,如果它实际上不是有效指针,则可能会崩溃。
例如。假设我将一个未初始化的 char 数组从 C 传递给 Go 函数,运行时如何解释该内存中的 Go 指针?
如果传递给 Go 的未初始化数据的类型不包含任何指针,则不应发生此错误。因此,特别是对于 char
数组,无论哪种方式都应该没问题。
此外,“如果 Go 代码将在其中存储指针值”部分让我感到困惑。为什么以后使用此内存很重要?
编译器在指针类型的存储指令中插入写屏障。如果 Go 程序不存储指针,那么编译器不会发出任何写屏障,也不会触发写屏障中的 bug。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。