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 <[email protected] <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 [email protected].
For more options, visit https://groups.google.com/d/optout.