使用cgofuse时CGO传入的byte buffer可读但写入报错是什么原因?
问题原因
你遇到的写入错误和CGO的使用场景直接相关,核心原因是:
Write方法传入的buff切片的底层数组是FUSE的C实现层分配的只读内存缓冲区,是操作系统内核向FUSE驱动传递写入数据时分配的只读页,仅允许上层读取内容,不允许修改。- 你尝试修改
buff[0]的操作本质是写入只读内存页,在Windows下直接触发访问违例错误(错误码0xc0000005就是典型的无权限访问内存的错误码)。 - 你能正常读取
buff[0]的内容、打印len和cap都没问题,是因为这块内存有可读权限,只是没有可写权限。
是不是CGO导致的?
确实和CGO的使用有关,但不属于CGO本身的bug:
CGO只负责把C侧分配的内存地址包装成Go的切片传递给上层业务代码,但是这块内存的访问权限是由底层FUSE的C实现决定的,cgofuse库的接口约定就是buff参数为只读,不允许修改。
解决方法
如果你确实需要修改写入的内容,必须先把buff的内容拷贝到Go runtime自己管理的可写内存中再操作,示例如下:
func (self *Memfs) Write(path string, buff []byte, ofst int64, fh uint64) (n int) { defer trace(path, buff, ofst, fh)(&n) defer self.synchronize()() node := self.getNode(path, fh) if nil == node { return -fuse.ENOENT } endofst := ofst + int64(len(buff)) if endofst > node.stat.Size { node.data = resize(node.data, endofst, true) node.stat.Size = endofst } // 先拷贝到Go分配的可写切片 localBuf := make([]byte, len(buff)) copy(localBuf, buff) localBuf[0] = 1 // 此处操作不会报错 n = copy(node.data[ofst:endofst], localBuf) tmsp := fuse.Now() node.stat.Ctim = tmsp node.stat.Mtim = tmsp return }
内容的提问来源于stack exchange,提问作者liang
相关产品推荐
相关产品推荐

