向golang中的内存位置写入但不从中读取时,SIGSEGV
我的印象是,使用向golang中的内存位置写入但不从中读取时,SIGSEGV,go,Go,我的印象是,使用不安全的包可以读取/写入任意数据。我试图更改接口{}指向的值,而不更改指针本身 假设接口{}实现为 type _interface struct { type_info *typ value unsafe.Pointer } 虽然读取成功,但SIGSEGV设置失败 func data(i interface{}) unsafe.Pointer { return unsafe.Pointer((*((*[2]uintptr)(unsafe.Pointer(
不安全的
包可以读取/写入任意数据。我试图更改接口{}
指向的值,而不更改指针本身
假设接口{}
实现为
type _interface struct {
type_info *typ
value unsafe.Pointer
}
虽然读取成功,但SIGSEGV设置失败
func data(i interface{}) unsafe.Pointer {
return unsafe.Pointer((*((*[2]uintptr)(unsafe.Pointer(&i))))[1])
}
func main() {
var i interface{}
i = 2
fmt.Printf("%v, %v\n", (*int)(data(i)), *(*int)(data(i)))
*((*int)(data(i))) = 3
}
我做错了什么事,还是在golang不可能。。。下面是我目前如何理解您的第二个代码示例,以防我犯了错误(如果您注意到我所描述的内容有任何错误,我的答案可能是无可挽回的错误,您应该忽略我要说的其他内容)
main
中的接口i
分配内存i
的值设置为值为2的整数类型数据中的接口i
分配内存
i
值复制到data的i
;也就是说,将新接口的值设置为值为2的整数类型uintpttr
的length-2数组的指针(使用unsafe.pointer
作为强制编译器接受此强制转换的中介)data
中i
的值部分的地址)强制转换回不安全的.指针
,并返回它go vet
抱怨,我认为这是因为,根据
uintptr是整数,不是引用。将指针转换为uintptr将创建一个没有指针的整数值
语义学。即使uintptr持有某个对象的地址,垃圾收集器也不会在对象移动时更新该uintptr的值,该uintptr也不会阻止对象被回收
更重要的是,据我所知(尽管我承认在不扫描编译器和运行时源代码的情况下挖掘显式确认时遇到了困难),运行时似乎不会跟踪接口{}
类型的值部分,因为它是一个带有自己引用计数的离散指针;当然,您可以将接口{}
中的两个字都压在整个过程中,但这似乎根本不是您想要做的事情(写入接口类型中指针的内存地址,而无需移动指针)
有趣的是,我们似乎能够定义自己的结构化类型,而编译器没有对其进行特殊处理(接口显然有些特殊,带有类型断言语法等等)。也就是说,我们可以使用unsafe.Pointer
来维护指向内存中特定点的引用,并且无论我们将其强制转换到什么位置,即使值发生变化,内存地址也不会移动(并且可以通过将其强制转换到其他位置来重新解释该值)。让我有点吃惊的是,至少在我自己的例子中,至少在操场环境中,所指向的值似乎没有固定的大小;我们可以建立一个要写入一次的地址,即使数据量很大(或很小),重复写入该地址也会成功
当然,至少在这个实现中,我们失去了许多其他和接口类型相关联的东西,特别是非空接口类型(即方法)。所以,没有办法用它来(例如)制作一个超级鬼鬼祟祟的“泛型”类型。一个接口似乎是它自己的值,该值定义的一部分是内存中的地址,但它与指针并不完全相同