Search code examples
gocgo

How do I release the memory allocated by C.CString?


Here is my code:

helloworld.go:

package main

import "C"
import "unsafe"

//export HelloWorld
func HelloWorld() *C.char {
    cs := C.CString("Hello World!")
    C.free(unsafe.Pointer(cs))
    return cs
}

func main() {}

One of the errors I got:

src/helloworld.go:9:2: could not determine kind of name for C.free

Based on this article: https://blog.golang.org/c-go-cgo

I also found out that I need to add #include <stdlib.h> at top of my C file.

helloworld.h:

#include <stdlib.h>
/* Created by "go tool cgo" - DO NOT EDIT. */

/* package command-line-arguments */

/* Start of preamble from import "C" comments.  */




/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern char* HelloWorld();

#ifdef __cplusplus
}
#endif

I tried it to no success.

I need to free the memory.

How do I do this? Because in there example it prints out the string. I want to return it. Without C.free. I am able to do it. I am just worried of causing a memory leak or some other issue.


Solution

  • Command cgo

    // Go string to C string
    // The C string is allocated in the C heap using malloc.
    // It is the caller's responsibility to arrange for it to be
    // freed, such as by calling C.free (be sure to include stdlib.h
    // if C.free is needed).
    func C.CString(string) *C.char
    

    If the import of "C" is immediately preceded by a comment, that comment, called the preamble, is used as a header when compiling the C parts of the package.

    For example,

    package main
    
    /*
    #include <stdlib.h>
    */
    import "C"
    
    import "unsafe"
    
    //export HelloWorld
    func HelloWorld() *C.char {
        cs := C.CString("Hello World!")
        C.free(unsafe.Pointer(cs))
        return cs
    }
    
    func main() {}