首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >runtime.SetFinalizer:无法确定C.Char的名称

runtime.SetFinalizer:无法确定C.Char的名称
EN

Stack Overflow用户
提问于 2020-06-20 06:28:32
回答 1查看 765关注 0票数 0

请考虑下面的示例go代码:

代码语言:javascript
复制
package main

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


import (
    "fmt"
    "runtime"
    "unsafe"
)

func main() {
    // Convert Go string to C string using C.CString
    cString := C.CString("Wold!")
    fmt.Printf("C.CString type: %T\n", cString)
    //C.free(unsafe.Pointer(cString)) // <-- this works, but I don't want to free it manually..

    runtime.SetFinalizer(&cString, func(t *C.Char) {
        C.free(unsafe.Pointer(t))
    })
}

我正在试验cGo,并试图释放cString。当我试图使用cString释放变量runtime.SetFinalizer时,我遇到了以下情况:

代码语言:javascript
复制
$ go build a.go 
# command-line-arguments
./a.go:22:41: could not determine kind of name for C.Char

请给我指出正确的方向。谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-20 22:06:59

当cgo系统将包装器转换为Go编译器所理解的内容时,它必须将每个C类型转换为Go类型,以满足不同的目的。事实证明,这不适用于您的情况(这是您看到的错误)。

这实际上是可以的,因为您的代码从一开始就不会以您想要的方式工作。当Go的垃圾收集器准备释放占用Go内存的Go对象时,运行时终结器将运行,但是C.Cstring返回一个不是Go内存的指针。特别是,请注意以下来自cgo文档的引号

// Go字符串到C字符串// C字符串使用malloc在C堆中分配。//调用方有责任安排它被//释放,例如调用C.free (确保包括stdlib.h //如果需要C.free )。func C.CString(string) *C.char

由于返回的字符串位于"C堆“上,因此Go垃圾收集器永远不会完成它。如果你的代码被编译的话,那将是一个没有操作的过程。

如果您有一个Go对象,其生存期与C对象的生存期类似,那么您也许可以使用它。下面是一个虚构的(但有效的)示例:

代码语言:javascript
复制
package main

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

import (
        "fmt"
        "runtime"
        "time"
        "unsafe"
)

type S struct {
        Foo    int
        ToFree unsafe.Pointer
}

func main() {
        doit()
        runtime.GC()
        time.Sleep(10 * time.Millisecond) // ugly hack
}

func doit() {
        cString := C.CString("Wold!")
        fmt.Printf("C.CString type: %T\n", cString)
        x := &S{Foo: 1, ToFree: unsafe.Pointer(cString)}
        runtime.SetFinalizer(x, func(t *S) {
                fmt.Println("freeing C string")
                C.free(t.ToFree)
        })
}

当为x分配的对象超出作用域时,它就有资格使用GC。实际的GC可能永远不会发生,所以我在main中强制使用了一个GC。这将触发终结器:

代码语言:javascript
复制
$ ./cfree_example
C.CString type: *main._Ctype_char
freeing C string

“丑陋的黑客”就在其中,因为如果main在终结器调用编写完freeing C string消息之前返回,它就会丢失。在一个真正的程序中,您将不需要这个。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62482446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档