根据地址偏移量(与平台/编译器无关)计算结构字段索引是否安全?
type T struct {
F1 int
F2 int
F3 string
F4 float64
F5 bool
}
t := new(T)
t.F1 = 1
t.F2 = 2
t.F3 = "hello wordl!"
t.F4 = 1234.7283823
t.F5 = true
fmt.Println("T address:", &t)
fmt.Println("t.F1 address:", &t.F1, "size: ", unsafe.Sizeof(t.F1), "offset: ", unsafe.Offsetof(t.F1), "value: ", t.F1)
fmt.Println("t.F2 address:", &t.F2, "size: ", unsafe.Sizeof(t.F2), "offset: ", unsafe.Offsetof(t.F2), "value: ", t.F2)
fmt.Println("t.F3 address:", &t.F3, "size: ", unsafe.Sizeof(t.F3), "offset: ", unsafe.Offsetof(t.F3), "value: ", t.F3)
fmt.Println("t.F4 address:", &t.F4, "size: ", unsafe.Sizeof(t.F4), "offset: ", unsafe.Offsetof(t.F4), "value: ", t.F4)
fmt.Println("t.F5 address:", &t.F5, "size: ", unsafe.Sizeof(t.F5), "offset: ", unsafe.Offsetof(t.F5), "value: ", t.F5)
Run Code Online (Sandbox Code Playgroud)
编辑
也许偏移字使这个问题有些混乱。当上面的代码运行时,地址空间正在增长。我想知道的是,结构字段是否按其定义顺序分配。
“安全吗”好吧,让我停在那里。您正在使用一个名为unsafe的软件包。
“如果不对垃圾收集器之类的东西做任何根本性的改变,这通常可以预期吗?” 是的,可能
从unsafe文档中OffsetOf:
Offsetof返回v表示的字段的结构内的偏移量,该偏移量的格式必须为structValue.field。换句话说,它返回结构开始与字段开始之间的字节数。
换句话说,一定要考虑对齐等问题。unsafe.Pointer(uintptr(&t) + unsafe.OffsetOf(t.F1))保证是在那个精确的时刻指向F1该特定实例的字段的实际不安全地址的实际不安全指针t。
您仍然必须非常小心unsafe,出于垃圾收集目的,不安全的指针通常不会被视为对对象的“引用”。因此,如果您对该对象的唯一引用是指向该字段的不安全指针,则可能会发生奇怪的事情。另外,有一种说法是要实现“压缩GC”,这意味着在垃圾回收内存上可能会乱码,这意味着除非您固定对象(将与压缩GC一起添加),否则不安全的指针会自发地变成在您不知道的情况下无效(当然,正常的指针将保持不变)。
如果您确定会保留对它的引用,并且对以后的更改完全破坏您的代码还可以,请继续尝试。我的意思是,绝对确保您需要使用不安全的方法,但是,如果您认为这是解决问题的最佳或唯一的解决方案,请在假定您已接受这些风险的情况下进行。
编辑:至于“内存顺序”业务。好吧,我们只能说我在规范中找不到可以确保结构按现场顺序排列的参考。就是说,某些事情encoding/binary.Read会使……我们应该说……如果不是的话,就没有多大意义。
因此,不要在超级技术意义上“依赖”,但是对于任何主流的Go编译器,您都可以确信字段按内存顺序排列-带来了所有与字对齐和打包有关的常见警告。
| 归档时间: |
|
| 查看次数: |
445 次 |
| 最近记录: |