【问题标题】:Why Go's 4bytes aligned struct address after mod 8 is 4 in 64-bit arch?为什么在 64 位拱门中 mod 8 后 Go 的 4 字节对齐结构地址是 4?
【发布时间】:2020-05-26 16:06:58
【问题描述】:

当我在 sync.WaitGroup 中研究代码时, 我注意到 WaitGroup 使用 state1([3]uint32) 字段来假设状态原子存储的 64 位对齐指针。

像这样:

// https://github.com/golang/go/issues/19149
type WaitGroup struct {
    noCopy noCopy
    state1 [3]uint32
}

// state returns pointers to the state and sema fields stored within wg.state1.
func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {
    if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
        return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2]
    } else {
        return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0]
    }
}

但是当我在 mac 和 linux 上检查这个时, 在 64 位系统上,第一个分配的 4 字节对齐数据结构地址显示在 mod 8 之后是 4,而在 32 位系统上是 0

我很好奇它在 golang 中是如何保证的?

代码在这里:https://play.golang.org/p/oiZMHd2c0I6

// 32-bit system:
// GOARCH=386 go run main.go
// 0 4 0 //why first address mod 8 is 0

// 64-bit system:
// go run main.go
// 4 0 4 //why first address mod 8 is 4

更新: 使用@Renat 的答案地址,不能保证变量地址。 输出可能不包含。

【问题讨论】:

  • "在 mod 8 为 4 后,在 64 位中显示 4 字节对齐的地址,在 32 位拱门上为 0"。或许你能解释一下这句话?
  • @Volker 抱歉之前的解释很差,我只是改一下。

标签: go 32bit-64bit memory-alignment


【解决方案1】:

来自golang.org

计算机架构可能需要对齐内存地址; 也就是说,对于一个变量的地址是一个因子的倍数, 变量类型的对齐方式。函数 Alignof 接受一个表达式 表示任何类型的变量并返回 (type 的) 变量,以字节为单位。

因此,鉴于Alignof(c)4,它将与4 对齐,而不需要与8 字节对齐。

当创建M的另一个对象时

var c = M{}
var d = M{}
println(
    unsafe.Sizeof(c),
    unsafe.Alignof(c),
    uintptr(unsafe.Pointer(&c.x))%8,
)
println(
    "    ",
    uintptr(unsafe.Pointer(&d.x))%8,
)

我明白了:

12 4 4
     0

【讨论】:

  • 你的回答启发了我,我猜,structM的第一个alloc地址是8对齐的地址,然后加上4bytes的偏移量,最后12bytes可以适合[3]uint32。所以d mod 8 现在是 0。 --- 如果稍后添加var e = MM{}uintptr(unsafe.Pointer(&c.x))%8 将再次为 4 是真的吗?我添加了一些代码来测试这种情况:play.golang.org/p/oiZMHd2c0I6
  • @newbmiao , And if add var e = MM{} later, uintptr(unsafe.Pointer(&c.x))%8 will be 4 again ,我认为不能保证。而且在垃圾回收之后,变量可能会改变它自己的地址(更详细:stackoverflow.com/questions/22195919/…),所以即使是单个变量也可能会得到address % 8 == 4,然后是address % 8 == 0(如果它有4字节对齐)
猜你喜欢
  • 2021-08-22
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2018-03-12
  • 2023-03-28
  • 2015-05-28
  • 1970-01-01
相关资源
最近更新 更多