对为什么这个 cgo 代码 panic 感到困惑
Confused about why this cgo code panic
想写一个使用golang调用c函数的demo,写了这个文件,发现会出现panic,不知道为什么。
首先是一个c头文件p.h
:
void output(char* str, int s);
void cc(char *str);
二、一个c文件p.c
:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void output(char* str, int s) {
fflush(stdout);
sleep(s);
printf("%s", str);
}
void cc(char *str) {
printf("%s", c_ccB(str));
}
很简单,go代码一个output
函数,go代码一个cc
函数调用c_ccB
,最后一个go代码文件是p.go
:
package main
/*
#include<stdlib.h>
#include "p.h"
*/
import "C"
import "unsafe"
import "fmt"
//export c_ccB
func c_ccB(cs *C.char) *C.char {
gs := C.GoString(cs)
return C.CString(gs + "wwww")
}
func main() {
ch := make(chan int)
task("A", ch, 5)
task("B", ch, 1)
fmt.Printf("begin\n")
<-ch
}
func task(name string, ch chan int, s int) {
go func() {
i:= 1
for {
str := ":" + name
cstr := C.CString(str)
C.output(cstr, C.int(s))
C.cc(cstr)
C.free(unsafe.Pointer(cstr))
i++
}
ch <- 1
}();
}
go代码就是两个goroutime不断打印一些字符串,如果删除C.cc(cstr)
就可以了,但是为什么C.cc
会引起panic呢?它只是在 go.
中调用 func c_ccB
这是紧急消息:
begin
:B:Bwwww:B:Bwwww:B:Bwwww:B:Bwwwwfatal error: unexpected signal during runtime execution
[signal 0xb code=0x1 addr=0x900008e0 pc=0x7ff5973f8c80]
runtime stack:
runtime.throw(0x5438a0, 0x2a)
/usr/local/go/src/runtime/panic.go:547 +0x90
runtime.sigpanic()
/usr/local/go/src/runtime/sigpanic_unix.go:12 +0x5a
goroutine 5 [syscall, locked to thread]:
runtime.cgocall(0x4b1b20, 0xc82002bf20, 0x0)
/usr/local/go/src/runtime/cgocall.go:123 +0x11b fp=0xc82002bee8 sp=0xc82002beb8
main._Cfunc_cc(0x7ff5900008c0)
_/home/suwey/code/go/src/_obj/_cgo_gotypes.go:62 +0x36 fp=0xc82002bf20 sp=0xc82002bee8
main.task.func1(0x51bf48, 0x1, 0x5, 0xc820062060)
/home/suwey/code/go/src/p.go:32 +0xae fp=0xc82002bfa0 sp=0xc82002bf20
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1998 +0x1 fp=0xc82002bfa8 sp=0xc82002bfa0
created by main.task
/home/suwey/code/go/src/p.go:37 +0x53
goroutine 1 [chan receive]:
main.main()
/home/suwey/code/go/src/p.go:22 +0xda
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1998 +0x1
goroutine 6 [syscall, locked to thread]:
main._Cfunc_output(0x1de38b0, 0x1)
_/home/suwey/code/go/src/_obj/_cgo_gotypes.go:74 +0x3a
main.task.func1(0x51bfd0, 0x1, 0x1, 0xc820062060)
/home/suwey/code/go/src/p.go:31 +0xa0
created by main.task
/home/suwey/code/go/src/p.go:37 +0x53
您在 C 代码中错过了 c_ccB
的声明。请加extern char* c_ccB(char*);
给你p.c
而且,您忘记释放在 c_ccB
中分配给 CString
的内存。
想写一个使用golang调用c函数的demo,写了这个文件,发现会出现panic,不知道为什么。
首先是一个c头文件p.h
:
void output(char* str, int s);
void cc(char *str);
二、一个c文件p.c
:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void output(char* str, int s) {
fflush(stdout);
sleep(s);
printf("%s", str);
}
void cc(char *str) {
printf("%s", c_ccB(str));
}
很简单,go代码一个output
函数,go代码一个cc
函数调用c_ccB
,最后一个go代码文件是p.go
:
package main
/*
#include<stdlib.h>
#include "p.h"
*/
import "C"
import "unsafe"
import "fmt"
//export c_ccB
func c_ccB(cs *C.char) *C.char {
gs := C.GoString(cs)
return C.CString(gs + "wwww")
}
func main() {
ch := make(chan int)
task("A", ch, 5)
task("B", ch, 1)
fmt.Printf("begin\n")
<-ch
}
func task(name string, ch chan int, s int) {
go func() {
i:= 1
for {
str := ":" + name
cstr := C.CString(str)
C.output(cstr, C.int(s))
C.cc(cstr)
C.free(unsafe.Pointer(cstr))
i++
}
ch <- 1
}();
}
go代码就是两个goroutime不断打印一些字符串,如果删除C.cc(cstr)
就可以了,但是为什么C.cc
会引起panic呢?它只是在 go.
func c_ccB
这是紧急消息:
begin
:B:Bwwww:B:Bwwww:B:Bwwww:B:Bwwwwfatal error: unexpected signal during runtime execution
[signal 0xb code=0x1 addr=0x900008e0 pc=0x7ff5973f8c80]
runtime stack:
runtime.throw(0x5438a0, 0x2a)
/usr/local/go/src/runtime/panic.go:547 +0x90
runtime.sigpanic()
/usr/local/go/src/runtime/sigpanic_unix.go:12 +0x5a
goroutine 5 [syscall, locked to thread]:
runtime.cgocall(0x4b1b20, 0xc82002bf20, 0x0)
/usr/local/go/src/runtime/cgocall.go:123 +0x11b fp=0xc82002bee8 sp=0xc82002beb8
main._Cfunc_cc(0x7ff5900008c0)
_/home/suwey/code/go/src/_obj/_cgo_gotypes.go:62 +0x36 fp=0xc82002bf20 sp=0xc82002bee8
main.task.func1(0x51bf48, 0x1, 0x5, 0xc820062060)
/home/suwey/code/go/src/p.go:32 +0xae fp=0xc82002bfa0 sp=0xc82002bf20
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1998 +0x1 fp=0xc82002bfa8 sp=0xc82002bfa0
created by main.task
/home/suwey/code/go/src/p.go:37 +0x53
goroutine 1 [chan receive]:
main.main()
/home/suwey/code/go/src/p.go:22 +0xda
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1998 +0x1
goroutine 6 [syscall, locked to thread]:
main._Cfunc_output(0x1de38b0, 0x1)
_/home/suwey/code/go/src/_obj/_cgo_gotypes.go:74 +0x3a
main.task.func1(0x51bfd0, 0x1, 0x1, 0xc820062060)
/home/suwey/code/go/src/p.go:31 +0xa0
created by main.task
/home/suwey/code/go/src/p.go:37 +0x53
您在 C 代码中错过了 c_ccB
的声明。请加extern char* c_ccB(char*);
给你p.c
而且,您忘记释放在 c_ccB
中分配给 CString
的内存。