c++gocgo

How to correctly free memory when using CString with cgo in golang?


I'm trying to understand how to correctly free memory when using CString with cgo in golang

This is the working code that I want to make "memory-safe":

basic.go :

package main

// #include <stdlib.h>
import "C"

import (
        "github.com/pemistahl/lingua-go"
)

var lan lingua.Language


//export Langdetectfunct
func Langdetectfunct(text *C.char) int {


    textS := C.GoString(text);

    detector := lingua.NewLanguageDetectorBuilder().
        FromAllLanguages().
        Build()

    language, _ := detector.DetectLanguageOf(textS)

    return int(language)

}

func main() {}

basic1.cpp :

#include "basic.h"

int main() {
    auto text = "It is a beautiful day, today";
    int res = Langdetectfunct(const_cast<char *>(text));
    std::cout << "res: " << res << std::endl;
}

After building basic.go with c-shared buildmode:

raphy@raohy:~/go-lang-detect$ go build -o basic.so -buildmode=c-shared basic.go

and compiling basic1.cpp with basic.so :

raphy@raohy:~/go-lang-detect$ g++ -o basic basic1.cpp ./basic.so

I get the correct output:

raphy@raohy:~/go-lang-detect$ ./basic 
res: 17

And that's fine...

But: how to make the code "memory-safe"?

I tried in this way:

basic.go :

package main

// #include <stdlib.h>
import "C"
import "unsafe"

import (
        "github.com/pemistahl/lingua-go"
)

var lan lingua.Language

//export Langdetectfunct
func Langdetectfunct(text *C.char) int {

    textS := C.GoString(text);

    detector := lingua.NewLanguageDetectorBuilder().
        FromAllLanguages().
        Build()

    language, _ := detector.DetectLanguageOf(textS)

    return int(language)

    C.free(unsafe.Pointer(text))
}

func main() {}

But, when, building, I get, understandably, this error:

raphy@raohy:~/go-lang-detect$ go build -o basic.so -buildmode=c-shared basic.go
./basic.go:39:1: missing return

If I put C.free(unsafe.Pointer(text)) before the return statement:

package main

// #include <stdlib.h>
import "C"
import "unsafe"

import (
        "github.com/pemistahl/lingua-go"
)

var lan lingua.Language

//export Langdetectfunct
func Langdetectfunct(text *C.char) int {

    textS := C.GoString(text);

    detector := lingua.NewLanguageDetectorBuilder().
        FromAllLanguages().
        Build()

    language, _ := detector.DetectLanguageOf(textS)

    C.free(unsafe.Pointer(text))

    return int(language)

}

func main() {}

I get : free(): invalid pointer error, when running the executable:

raphy@raohy:~/go-lang-detect$ go build -o basic.so -buildmode=c-shared basic.go
raphy@raohy:~/go-lang-detect$ g++ -o basic basic1.cpp ./basic.so
raphy@raohy:~/go-lang-detect$ ./basic 
free(): invalid pointer
Aborted (core dumped)

Solution

  • auto text = "It is a beautiful day, today";

    text is in the Stack place. You can't free it.