On Thu, Aug 17, 2017 at 06:50:42PM -0700, jianzhang...@gmail.com wrote:

> > > As the instruction 
> > > of https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices 
> > > shows, the GC of Go will not release it. 
> > > An example as the following, but I have a question about when and how to 
> > > release this `slice`? 
> >
> > You shouldn't: the GC won't touch the memory it does not "own" so it 
> > will eventually collect the slice structure itself but won't do anything 
> > to its underlying array (which value you obtained via that double 
> > type-conversion). 
> >
> > You should supposedly be instead concerned with freeing the array's 
> > memory (via calling C.free or some dedicated function to do this 
> > provided by your C side, if any).  As always with C, you should only do 
> > that if that getTheArray() function's semantics are such that its caller 
> > "owns" the memory the function returns. 
[...]
> Thanks your reply, you mean I should be release the memory of `theCArray` 
> in C side?
> I still have some doubts, and I made a clearer example as the below, any 
> problem with it?

I see no reason to defer calls to C.free().
defer is a costly operation, and it should be only used if the resource
the deferred call is intended to free can be used in arbitrary places
down the code paths after it's allocated; that's not the case there.

> So, the memory of this tmpslice should be release by release the argv on C 
> side?

Yes and no.

Yes, if that memory was produced by a function whose semantics are
"the caller is responsible to freeing the memory of the data I
returned", and no otherwise.

There can't be easy answer to a question like this in C.
Consider:

  // This function clearly transfers the ownership of the memory
  // it returns to the caller.
  int* allocate(int n)
  {
    int *mem = (int*)malloc(n * sizeof(int));
    if (mem == NULL) {
      panic("Out of memory");
    }
  }

  // But this one doesn't.
  int* find_first_non_zero(int *p, int count)
  {
    for (i = 0; i < count; i++) {
          if p[i] > 0 {
            return &p[i];
          }
        }
        return NULL;
  }

I tried to highlight that even though the latter function returns a
pointer to memory, its caller is not supposed to do anything with that
pointer (other than supposedly checking it for being non-NULL and
dereferencing otherwise).

You should apply the same logic to the code on your C side: if the
function which is used to obtain the value for the "argv" argument
of GoStrings() actually allocates the memory and supposes its caller has
to deallocate it theirselves, go on and free it.  Otherwise don't.

> func GoStrings(length int, argv **C.char) []string {
>         
>         tmpslice := (*[1 << 30]*C.char)(unsafe.Pointer(argv))[:length:length
> ]
>         gostrings := make([]string, length)
>         for i, s := range tmpslice {
>                 gostrings[i] = C.GoString(s)
>                 defer C.free(unsafe.Pointer(s))
>         }
>         return gostrings
> }
> 

-- 
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