在使用cgo和golang中的free时出现了”double free or corruption (out)”错误。

huangapple go评论93阅读模式
英文:

Getting double free or corruption (out) when using free in cgo, golang

问题

我正在尝试理解和学习cgo,并在此过程中编写了一个使用C.stat检查文件权限的函数。

在传递文件路径给该函数时,它报错如下:

*** Error in '/tmp/Build go-sync.go and run77go': double free or corruption (out): 0x0000000000609480 ***
SIGABRT: abort
PC=0x7fe4302f3267 m=0
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x401930, 0xc820097808, 0xc800000000)
/usr/lib/go/src/runtime/cgocall.go:120 +0x11b fp=0xc8200977d8 sp=0xc8200977a8
gosyncmodules._Cfunc_free(0x609480)
==========snip============

因为最后一行gosyncmodules._Cfunc_free(0x609480),我移除了defer C.free(unsafe.Pointer(statt)),然后它就正常工作了。

  • 为什么在尝试释放创建的结构体时会出错,而可以用来释放路径变量?
  • 在这种情况下,类似的情景会导致内存泄漏吗?
英文:

I am trying to understand and learn cgo, and as a part of that, I wrote a function that checks for filepermission using C.stat.

import (
    "fmt"
    "unsafe"
    "os"
)
//#include <sys/stat.h>
//#include <stdlib.h>
import "C"

func CheckPerm(filename string) {

    statt := C.stat //stat struct from C
    path := C.CString(filename)
    st := *(*C.struct_stat)(unsafe.Pointer(statt)) //Casting unsafe pointer to C.struct_stat
    defer C.free(unsafe.Pointer(path)) //free
    defer C.free(unsafe.Pointer(statt))
    C.stat(path, &st)
    if st.st_mode & C.S_IRGRP > 0 || st.st_mode & C.S_IWGRP > 0 || st.st_mode & C.S_IXGRP > 0 || st.st_mode & C.S_IROTH > 0 || st.st_mode & C.S_IWOTH > 0 || st.st_mode & C.S_IXOTH > 0 {
	    fmt.Println("file permission too broad, make it non-readable to groups and others.")
	    os.Exit(1)
    }
    fmt.Println("File permission looks fine")

}

Upon passing a filepath to the function, it errors out saying

*** Error in `/tmp/Build go-sync.go and run77go': double free or corruption (out): 0x0000000000609480 ***
SIGABRT: abort
PC=0x7fe4302f3267 m=0
signal arrived during cgo execution

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x401930, 0xc820097808, 0xc800000000)
/usr/lib/go/src/runtime/cgocall.go:120 +0x11b fp=0xc8200977d8 sp=0xc8200977a8
gosyncmodules._Cfunc_free(0x609480)
==========snip============

Because of the last line pasted here gosyncmodules._Cfunc_free(0x609480), I removed the defer C.free(unsafe.Pointer(statt)) and it works fine now.

  • Why is it throwing error when I am trying to free the struct that was created, whereas it can be used to free the path variable?
  • Will a similar scenario cause a memory leak, if not in this case?

答案1

得分: 2

https://golang.org/cmd/cgo/#hdr-Go_references_to_C

// Go字符串转换为C字符串
// C字符串在C堆中使用malloc分配。
// 调用者有责任安排它被释放,例如通过调用C.free(如果需要,请确保包含stdlib.h)。
func C.CString(string) *C.char

你的

path := C.CString(filename)

会创建一个副本,你需要在使用完后释放它,而statt是一个普通的Go内存管理变量。

英文:

From https://golang.org/cmd/cgo/#hdr-Go_references_to_C :

// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char

Your

path := C.CString(filename)

makes a copy and you have to free it while statt is a normal Go-memory-managed variable.

huangapple
  • 本文由 发表于 2016年2月17日 19:40:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/35455702.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定