我正在尝试使用CGO从golang调用复杂算法的优化C ++ CPU绑定实现。基本上,它会将一个字符串传递给c ++函数并返回一个字符串。代码的简化版本可以在下面看到:
//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;
}
}
在这个链接中,ppl提到C ++代码应该自己调用“free”来释放分配的内存:http://grokbase.com/t/gg/golang-nuts/149hxezftf/go-nuts-cgo-is-it-safe-to-malloc-and-free-in-seperate-c-functions。但是它非常棘手,因为我的c ++函数返回一个已分配的指针,以便golang可以获得结果。我不能在c ++代码中免费拨打电话?处理这个问题的正确方法应该是什么?我有一个网络服务器会根据每个请求调用c ++代码,并希望确保它不会引入任何内存泄漏。
感谢。
答案 0 :(得分:1)
修复echo
功能中的内存分配错误。例如,
algo.go
:
//algo.go
package main
//#cgo LDFLAGS:
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//char* echo(char* s);
import "C"
import (
"fmt"
"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))
fmt.Println(C.GoString(echoOut))
}
algo.cpp
:
//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) {
char* out = (char*)malloc(strlen(o)+1);
strcpy(out, o);
return out;
}
}
输出:
$ cd algo
$ go build && ./algo
Hello from stdio
$
答案 1 :(得分:0)
我使用以下版本go version go1.8 linux/amd64
并且在取消注释延迟的C.free后运行代码时没有任何问题。
我添加了一个循环,允许我通过htop跟踪内存泄漏。没有延期免费它会泄漏,但取消注释它可以解决问题。
代码如下。
//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() {
for i := 0; i < 1000000000; i++ {
allocateAndDeallocate()
}
}
func allocateAndDeallocate() {
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)) // no crash here
}
//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;
}
}