CGO:如何使用 malloc 从 go 释放 C 中分配的内存以避免内存泄漏



我正在尝试使用 CGO 从 golang 调用复杂算法的优化C++ CPU 密集型实现。基本上,它会将字符串传递到 c++ 函数中并取回字符串。代码的简化版本如下所示:

算法

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 stdion")
    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));
}

算法.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-separate-c-functions。但是这非常棘手,因为我的 c++ 函数返回一个分配的指针,以便 golang 可以得到结果。我不能在 c++ 代码中调用 free?处理这个问题的正确方法应该是什么?我有一个网络服务器将为每个请求调用c ++代码,并希望确保它不会引入任何内存泄漏。

谢谢。

修复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 stdion")
    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
$ 

我正在使用以下 go 版本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 stdion")
    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;
    }
}    

相关内容

  • 没有找到相关文章

最新更新