2019. február 25., hétfő 10:18:42 UTC+1 időpontban yang...@gmail.com a következőt írta: > > I'm sorry for the missed detail of Receive() function. Variable gReceive > (sorry > for the silly variable name) will be manipulated in Go, since some data > coversions in the latter loop. > > Function Receive(): > > func Receive( > devType int, > devIndex int, > canIndex int, > pReceive []CanObj, > waitTime int, > ) (count int, err error) { > cReceive := C.makeCanObjArray() > defer C.freeCanObjArray(cReceive) > cCount := C.VCI_Receive( > C.uint(devType), > C.uint(devIndex), > C.uint(canIndex), > (*C.struct__VCI_CAN_OBJ)(unsafe.Pointer(&cReceive)), > C.uint(FRAME_LENGTH_OF_RECEPTION), > C.int(waitTime), > ) > count = int(cCount) > switch count { > case -1: > return count, fmt.Errorf("failed to receive data from invalid device") > case 0: > return count, nil > } > gReceive := (*[1 << > 30]C.struct__VCI_CAN_OBJ)(unsafe.Pointer(&cReceive))[:count:count] > > for i := 0; i < count; i++ { > v := gReceive[i] > var data [8]byte > for j, d := range v.Data { > data[j] = byte(d) > } > var reserved [3]byte > for k, r := range v.Reserved { > reserved[k] = byte(r) > } > pReceive[i] = CanObj{ > ID: int(v.ID), > TimeStamp: int(v.TimeStamp), > TimeFlag: int(v.TimeFlag), > SendType: byte(v.SendType), > RemoteFlag: byte(v.RemoteFlag), > ExternFlag: byte(v.ExternFlag), > DataLen: byte(v.DataLen), > Data: data, > Reserved: reserved, > } > } > return count, err > } > > Thank you for the patience! > > > > On Monday, February 25, 2019 at 4:46:18 PM UTC+8, Tamás Gulácsi wrote: >> >> >> >> 2019. február 25., hétfő 9:10:19 UTC+1 időpontban yang...@gmail.com a >> következőt írta: >>> >>> Thank you! >>> >>> There is a pointer copied between Go and Cgo indeed, i.e., Go creates a >>> slice (pReceive) to Cgo, which reads data into it. It would be >>> reasonable when there are some panics occurred there. Actually, what >>> triggers the panic is the make-slice statements, i.e., cReceive := >>> make([]C.struct__CAN_OBJ, 2500), and pReceive := >>> make([]controlcan.CanObj, 2500). >>> >>> The C definition of C.struct__CAN_OBJ: >>> >>> typedef struct _VCI_CAN_OBJ{ >>> UINT ID; >>> UINT TimeStamp; >>> BYTE TimeFlag; >>> BYTE SendType; >>> BYTE RemoteFlag; >>> BYTE ExternFlag; >>> BYTE DataLen; >>> BYTE Data[8]; >>> BYTE Reserved[3]; >>> }VCI_CAN_OBJ,*PVCI_CAN_OBJ; >>> >>> My Go wrapper controlcan.CanObj: >>> >>> type CanObj struct { >>> ID int >>> TimeStamp int >>> TimeFlag int >>> SendType byte >>> RemoteFlag byte >>> ExternFlag byte >>> DataLen byte >>> Data [8]byte >>> Reserved [3]byte >>> } >>> >>> My use case is reading data from the wrapper periodically. >>> >>> package usbcan >>> >>> >>> import "controlcan" >>> >>> >>> func (c *Channel) receive() { >>> ticker := time.NewTicker(100 * time.Millisecond) >>> defer ticker.Stop() >>> for _ = range ticker.C { >>> pReceive := make([]controlcan.CanObj, 2500) // unexpected fault >>> address >>> count, err := controlcan.Receive( >>> c.DevType, >>> c.DevIndex, >>> c.CanIndex, >>> pReceive, >>> 100, >>> ) >>> // ... >>> >>> The Receive() function in controlcan package: >>> >>> func Receive( >>> devType int, >>> devIndex int, >>> canIndex int, >>> pReceive []CanObj, >>> waitTime int, >>> ) (count int, err error) { >>> cReceive := make([]C.struct__VCI_CAN_OBJ, 2500) // unexpected fault >>> address >>> cCount := C.VCI_Receive( >>> C.uint(devType), >>> C.uint(devIndex), >>> C.uint(canIndex), >>> (*C.struct__VCI_CAN_OBJ)(unsafe.Pointer(&cReceive)), >>> C.uint(FRAME_LENGTH_OF_RECEPTION), >>> C.int(waitTime), >>> ) >>> gReceive := (*[1 << 30]C.struct__VCI_CAN_OBJ)(unsafe.Pointer(& >>> cReceive))[:count:count] >>> // then convert elements in gReceive to pReceive >>> // ... >>> >>> My project is going to send instructions to devices concurrently. The >>> device communication protocol is provided as .so or .dll libraries. I >>> know it's complicated, but there will be more fun, isn't it? Fun, at least, >>> in the early peoriod. Recently I hate the runtime and gc a little bit ;) >>> >>> >>> On Monday, February 25, 2019 at 2:24:26 PM UTC+8, robert engels wrote: >>>> >>>> With GC off the free will not be called, nor will destructors be >>>> executed in response to finalizers, so many memory corruption errors will >>>> not be experienced (nor detected). >>>> >>>> Almost certainly the C memory is not being managed correctly - possibly >>>> copying a pointer between structs and then freeing the a pointer, with the >>>> other struct still holding a reference. >>>> >>>> I am guessing that the C.struct__CAN_OBJ also contains pointers ? >>>> >>>> Including the definition of that structure MIGHT help, but honestly, >>>> when you bind to C, you really need to be a C programmer and a Go >>>> programmer to do it correctly IMO. >>>> >>>> On Feb 24, 2019, at 7:58 PM, yang...@gmail.com wrote: >>>> >>>> HI all, >>>> >>>> Error unexpected fault address might be triggered by data race or >>>> memory >>>> corruption. After code review, I suspected the reasin is memory >>>> corruption instead >>>> of the data race. >>>> >>>> The following code panics occasionally, and yes, when I initialized >>>> silces. >>>> >>>> package controlcan >>>> >>>> import "C" >>>> >>>> cReceive := make([]C.struct__CAN_OBJ, 2500) >>>> >>>> or >>>> >>>> package usbcan >>>> >>>> import "controlcan" >>>> >>>> pReceive := make([]controlcan.CanObj, 2500) >>>> >>>> The error is: >>>> >>>> unexpected fault address 0xffffffffffffffff >>>> fatal error: fault >>>> [signal 0xc0000005 code=0x0 addr=0xffffffffffffffff pc=0x41c65d] >>>> >>>> >>>> goroutine 41 [running]: >>>> runtime.throw(0xcc969a, 0x5) >>>> /usr/local/go/src/runtime/panic.go:619 +0x88 fp=0xc0428ffb38 sp >>>> =0xc0428ffb18 pc=0x42d0b8 >>>> runtime.sigpanic() >>>> /usr/local/go/src/runtime/signal_windows.go:170 +0x13a fp= >>>> 0xc0428ffb68 sp=0xc0428ffb38 pc=0x43fcca >>>> runtime.gcMarkRootPrepare() >>>> /usr/local/go/src/runtime/mgcmark.go:72 +0x5d fp=0xc0428ffb70 >>>> sp=0xc0428ffb68 pc=0x41c65d >>>> runtime.gcStart(0x0, 0x1, 0x0, 0x0) >>>> /usr/local/go/src/runtime/mgc.go:1350 +0x30f fp=0xc0428ffba0 sp >>>> =0xc0428ffb70 pc=0x419b6f >>>> runtime.mallocgc(0x10000, 0xc54660, 0xc0422ee001, 0xc0423ded60) >>>> /usr/local/go/src/runtime/malloc.go:803 +0x448 fp=0xc0428ffc40 >>>> sp=0xc0428ffba0 pc=0x411c48 >>>> runtime.makeslice(0xc54660, 0x9c4, 0x9c4, 0xc04202ce00, 0xc04202c000, >>>> 0x411b23) >>>> /usr/local/go/src/runtime/slice.go:61 +0x7e fp=0xc0428ffc70 sp= >>>> 0xc0428ffc40 pc=0x43fffe >>>> controlcan.Receive(0x4, 0x0, 0x0, 0xc04267e000, 0x9c4, 0x9c4, 0x64, 0x0 >>>> , 0x0, 0x0) >>>> /media/sf_GOPATH0/src/controlcan/controlcan.go:262 +0x75 fp= >>>> 0xc0428ffd70 sp=0xc0428ffc70 pc=0xa0d795 >>>> posam/protocol/usbcan.(*Channel).receive(0xc04229d490) >>>> /media/sf_GOPATH0/src/posam/protocol/usbcan/usbcan.go:469 + >>>> 0x536 fp=0xc0428fffd8 sp=0xc0428ffd70 pc=0xa10926 >>>> runtime.goexit() >>>> /usr/local/go/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc0428fffe0 >>>> sp=0xc0428fffd8 pc=0x457531 >>>> created by posam/protocol/usbcan.(*Channel).Start >>>> /media/sf_GOPATH0/src/posam/protocol/usbcan/usbcan.go:242 + >>>> 0x3aa >>>> >>>> >>>> I got confused for couple of days, until I ran the app with GOGC=off. >>>> Everything works fine except the increasing memory usage. As what Dave >>>> Cheney >>>> said in cgo is not Go >>>> <https://dave.cheney.net/2016/01/18/cgo-is-not-go>, and JimB said at >>>> stackoverflow >>>> <https://stackoverflow.com/questions/26203617/golang-panic-fatal-error-from-c-code-unable-to-recover>, >>>> >>>> I realize that it is possible >>>> to trigger memory corruption when using cgo. But in the above >>>> situation, the >>>> only things required is the type CanObj, not any variables. >>>> >>>> So what is the reason behind this error, and how can I play well with >>>> GC and cgo? >>>> >>>> Here're links about this question: >>>> - https://github.com/golang/go/issues/30276 >>>> - >>>> https://stackoverflow.com/questions/54838040/does-data-race-happen-when-using-cgo >>>> >>>> Thank you! >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "golang-nuts" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to golang-nuts...@googlegroups.com. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>>> >>>> >> >> (*C.struct__VCI_CAN_OBJ)(unsafe.Pointer(&cReceive[0])) >> >> should be - a pointer to the first element of the slice, not the slice >> (struct) itself!!! >> >
You have to refer to the first element of the slice when using it as a C pointer-to-an-array! cReceive := make([]C.struct__VCI_CAN_OBJ, 2500) // unexpected fault address cCount := C.VCI_Receive( C.uint(devType), C.uint(devIndex), C.uint(canIndex), (*C.struct__VCI_CAN_OBJ)(unsafe.Pointer(&cReceive*[0]*)), C.uint(FRAME_LENGTH_OF_RECEPTION), C.int(waitTime), ) gReceive := (*[1 << 30]C.struct__VCI_CAN_OBJ)(unsafe.Pointer(&cReceive*[0]* ))[:count:count] -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.