package main /* #cgo CFLAGS: -g -Wall -I/usr/local/include #cgo LDFLAGS: -L/usr/local/lib -lm -lstdc++ #include <stdlib.h> #include <string.h> #include <stdint.h> #include <math.h>
// tet_pcos_get_string wraps the TET_pcos_get_string so we can use it in Go, cgo does not support // variadic args, this is the solution char* str_add(const char *s1, const char *s2) { char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator // in real code you would check for errors in malloc here strcpy(result, s1); strcat(result, s2); return result; } */ import "C" import ( "fmt" "unsafe" ) func main() { str := doTheCStuff() fmt.Println(str) } func doTheCStuff() string{ s1 := C.CString("string one") //defer C.free(unsafe.Pointer(file)) s2 := C.CString("string 2") //defer C.free(unsafe.Pointer(opt)) defer func(){ C.free(unsafe.Pointer(s1)) C.free(unsafe.Pointer(s2)) }() s3 := C.GoString(C.str_add(s1, s2)) return s3 } This is the sort of thing, this will run just fine and no re-produce the error. The exact use case in production where I see this involves using a 3rd party C library that opens a document. This then, sometimes, results in the error. The trouble is, using the 3rd party lib requires a license key so I'm not sure how much I can post on here. The actual snippet from prod that occasionally causes this issue is: // openDoc returns the document handle for the metadata extraction func (e *Extractor) openDoc(fp string) (*doc, error) { file := C.CString(fp) defer C.free(unsafe.Pointer(file)) opt := C.CString("shrug checkglyphlists=true decompose={none} tetml={elements={docinfo=true}} fold={{[U+0640] preserve} {[:Private_Use:] unknownchar} {[:space:] remove} {[U+0009] remove} {[U+000D] remove} {[:Control:] remove} {[:Unassigned:] preserve} {[U+FFFF] remove}} unknownchar=U+003F allowjpeg2000=true") defer C.free(unsafe.Pointer(opt)) // For documentation see page 175 docNum := C.TET_open_document(e.tet, file, 0, opt) if docNum < 0 { return nil, fmt.Errorf("failed to open document") } doc := &doc{ num: docNum, tet: e.tet, // added for convenience } return doc, nil } For this to work you need to have an instance ofTET and a license key. I can't share that, for obvious reason. But What you can see in this code is that I now have the more common pattern for create and free. Yet when I use the defer closure pattern here, after creating both file and opt, I sometimes get the double free. We have have noticed that the issue was reproducible with a specific set of files. Using this pattern fixes that issue, I'm just curious as to why the defer would cause trouble. On Thursday, October 11, 2018 at 9:23:23 AM UTC+1, Jan Mercl wrote: > > > On Thu, Oct 11, 2018 at 10:15 AM <nda...@turnitin.com <javascript:>> > wrote: > > > What I am wondering is why the closure approach does not work? > > ISTM it should work. Please post a full, standalone reproduction code here > or at the issue tracker, thanks. > > > -- > > -j > -- 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.