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.

Reply via email to