dqqpf32897
2017-11-11 11:24
浏览 95
已采纳

当C库使用不透明的结构指针时,如何解决CGO中的“写障碍错误指针”恐慌

I'm currently writing a Go wrapper around a C library. That C library uses opaque struct pointers to hide information across the interface. However, the underlying implementation stores size_t values in there. This leads to runtime errors in the resulting program. A minimum working example to reproduce the problem looks like this:

main.go:

package main

/*
#include "stddef.h"
// Create an opaque type to hide the details of the underlying data structure.
typedef struct HandlePrivate *Handle;

// In reality, the implementation uses a type derived from size_t for the Handle.
Handle getInvalidPointer() {
    size_t actualHandle = 1;
    return (Handle) actualHandle;
}
 */
import "C"

// Create a temporary slice containing invalid pointers.
// The idea is that the local variable slice can be garbage collected at the end of the function call.
// When the slice is scanned for linked objects, the GC comes across the invalid pointers.
func getTempSlice() {
    slice := make([]C.Handle, 1000000)
    for i, _ := range slice {
        slice[i] = C.getInvalidPointer()
    }
}

func main() {
    getTempSlice()
}

Running this program will lead to the following error

runtime: writebarrierptr *0xc42006c000 = 0x1
fatal error: bad pointer in write barrier
[...stack trace omitted...]

Note that the errors disappear when the GC is disabled by setting the environment variable GOGC=off.

My question is which is the best way to solve or work around this problem. The library stores integer values in pointers for the sake of information hiding and this seems to confuse the GC. For obvious reasons I don't want to start messing with the library itself but rather absorb this behaviour in my wrapping layer.

My environment is Ubuntu 16.04, with gcc 5.4.0 and Go 1.9.2.

Documentation of cgo

图片转代码服务由CSDN问答提供 功能建议

我目前正在用C库编写Go包装器。 该C库使用不透明的结构指针来隐藏整个接口中的信息。 但是,底层实现在其中存储size_t值。 这会导致结果程序中出现运行时错误。 重现此问题的最小工作示例如下:

main.go \ n

 程序包main 
 
 / * 
#include“ stddef.h” 
 //创建不透明的类型以隐藏基础数据结构的详细信息。
typedef struct HandlePrivate * Handle  ; 
 
 //实际上,该实现使用从size_t派生的类型作为Handle。
Handle getInvalidPointer(){
 size_t actualHandle = 1; 
 return(Handle)ActualHandle; 
} 
 * /  
import“ C” 
 
 //创建一个包含无效指针的临时切片。
 //这样的想法是,可以在函数调用结束时对本地变量切片进行垃圾回收。
 //当切片 
func getTempSlice(){
 slice:= make([] C.Handle,1000000)
 for i,_:= range slice {
 slice [  i] = C.getInvalidPointer()
} 
} 
 
func main(){
 getTempSlice()
} 
   
 
 

Runn 执行此程序将导致以下错误

 运行时:writebarrierptr * 0xc42006c000 = 0x1 
致命错误:写障碍中的指针错误
 [...堆栈跟踪被省略。  。] 
   
 
 

请注意,通过设置环境变量 GOGC = off 禁用GC时,错误消失了。 \ n

我的问题是解决或解决此问题的最佳方法。 该库将整数值存储在指针中,以便隐藏信息,这似乎使GC感到困惑。 出于明显的原因,我不想开始弄乱库本身,而是想在我的包装层中吸收这种行为。

我的环境是Ubuntu 16.04,带有gcc 5.4.0和Go 1.9 .2。

cgo文档

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

相关推荐 更多相似问题