你可以用Go“固定”内存中的对象吗?

时间:2012-08-23 19:07:19

标签: go

我有一个Go对象,其内存中的地址我想保持不变。在C#中,可以将对象的位置固定在内存中。有没有办法在Go中做到这一点?

2 个答案:

答案 0 :(得分:6)

您保留引用的对象不会移动。没有句柄或间接,你得到的地址是永久性的。

来自the documentation

  

请注意,与C不同,返回a的地址是完全可以的   局部变量;与变量关联的存储仍然存在   函数返回后

设置变量时,可以使用&运算符读取此地址,然后传递它。

答案 1 :(得分:0)

tl;dr no - 但没关系,除非你想做一些不寻常的事情。

值得注意的是,接受的答案部分不正确。

不能保证对象不会被移动——无论是在堆栈上还是在 Go 堆上——但只要你不使用 unsafe,这对你来说无关紧要,因为 Go 运行时会负责在移动对象时透明地更新您的指针。

如果 OTOH 您使用 unsafe 获取 uintptr、调用原始系统调用、执行 CGO 调用或以其他方式公开地址(例如 oldAddr := fmt.Sprintf("%p", &foo))等,您应该意识到地址可以更改,而且编译器和运行时都不会为您神奇地修补内容。

虽然目前标准 Go 编译器只移动堆栈上的对象(例如,当需要调整 goroutine 堆栈的大小时),但 Go 语言规范中没有任何内容阻止不同的实现在 Go 堆上移动对象。

>

虽然没有明确支持在堆栈或 Go 堆中固定对象,但有一个 recommended 解决方法:手动分配 Go 堆外的内存(例如通过 mmap)和一旦对它的所有引用都被删除,使用终结器自动释放该分配。这种方法的好处是在 Go 堆外手动分配的内存永远不会被 Go 运行时移动,所以它的地址永远不会改变,但它仍然会在不再需要时自动释放,所以它不会泄漏.