CGO: how to free memory allocated in C using malloc from go to avoid memory leak

1,654 views
Skip to first unread message

hiepkh...@gmail.com

unread,
Feb 19, 2016, 9:28:28 AM2/19/16
to golang-nuts
Hi,

I am trying to use CGO to call an optimized C++ CPU-bound implementation of a complex algorithms from golang. Basically, it will pass a string into c++ function and get a string back. A simplified version of the code can be seen in the below:

    //algo.go
    package main

//#cgo LDFLAGS:
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//char* echo(char* s);
import "C"
import "unsafe"

func main() {
cs := C.CString("Hello from stdio\n")
defer C.free(unsafe.Pointer(cs))
var echoOut *C.char = C.echo(cs)
//defer C.free(unsafe.Pointer(echoOut)); -> using this will crash the code
fmt.Println(C.GoString(echoOut));
}


//algo.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>

using namespace std;

extern "C" {
   char* echo(char* o) {
       int len = sizeof(o) / sizeof(char);
       char* out = (char*)malloc(len * sizeof(char));
       strcpy(out, o);
       return out;
   }
}    

In this link, ppl mentions that C++ code should call "free" by itself to free the allocated memory: http://grokbase.com/t/gg/golang-nuts/149hxezftf/go-nuts-cgo-is-it-safe-to-malloc-and-free-in-seperate-c-functions. But then it's very tricky because my c++ function return an allocated pointer so that golang can get the result. I cannot call free in the c++ code? What should be the correct way to handle this? I have a webserver will call the c++ code per each request and want to make sure it doesn't introduce any memory leak.

Thanks.

PS: another side questions, my actual c++ function is something like: char* lsh_hash(char* text, char* vectors_key); whereas vectors_key is a big object. I am current using: cVectorsKey := C.CString(string(byte_arr)); and then get the data like: C.GoString(C.lsh_hash(cText, cVectorsKey)). I assume that it will only pass pointer into c++ function but want to double confirm if it's best way to handle long vector_key or I should somehow manage to set vector key inside c++ code as global variable to avoid passing data from go function into c++ function. 

 

mjy

unread,
Feb 19, 2016, 9:47:09 AM2/19/16
to golang-nuts
Code looks OK for my superficial understanding, except you allocate space for a pointer and not for the string:

       int len = sizeof(o) / sizeof(char);

Should probably be strlen(o) ...

-mjy 

auxdx

unread,
Feb 20, 2016, 10:15:10 AM2/20/16
to golang-nuts
Hi,

Also, I just realize that my code are actually leaking memory. Seems that i would have to somehow free the allocated (malloc) memory within C code or finding a workaround solution, for example, initialize string in gocode and pass the pointer into c++ code in which c++ will use to copy the result into?

Is this a better way to handle?

auxdx

unread,
Feb 20, 2016, 10:15:11 AM2/20/16
to golang-nuts
Thanks,

Seems that the reason it crash before is because I allocated memory within c++ wrongly.

But i am still wondering if I should free the memory in go code using: defer C.free(unsafe.Pointer(echoOut)) for each cgo function call. Or have to free the memory somehow in the c++ code? (for example, having a static library instead of allocated it using malloc).

It was mentioned overhere that: go code has no idea how to release c++ dynamically allocated memory. http://grokbase.com/t/gg/golang-nuts/149hxezftf/go-nuts-cgo-is-it-safe-to-malloc-and-free-in-seperate-c-functions. Are they correct?

On Friday, 19 February 2016 22:47:09 UTC+8, mjy wrote:

Tamás Gulácsi

unread,
Feb 20, 2016, 10:57:27 AM2/20/16
to golang-nuts
C.free should work, if it is not, then another error is on the C side.
Reply all
Reply to author
Forward
0 new messages