同类型变量之间的地址间隙不同

问题描述 投票:0回答:1

我注意到,在某些版本的 Go 上,有时第一个和第二个 int 变量之间的差距会增加。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    a := 7
    b := 8
    c := 9
    d := 10
    fmt.Printf("a's address is %v\n", &a)
    fmt.Printf("b's address is %v\n", &b)
    fmt.Printf("c's address is %v\n", &c)
    fmt.Printf("d's address is %v\n", &d)

    baSpan := uintptr(unsafe.Pointer(&b)) - uintptr(unsafe.Pointer(&a))
    cbSpan := uintptr(unsafe.Pointer(&c)) - uintptr(unsafe.Pointer(&b))
    dcSpan := uintptr(unsafe.Pointer(&d)) - uintptr(unsafe.Pointer(&c))

    // Go playground, Go 1.20 - Prints 8.
    // Go playground, Go dev branch - Sometimes prints 8, sometimes 24.
    // My machine, go1.20.4 windows/amd64 - Always prints 24.
    fmt.Printf("b-a span is %v\n", baSpan)

    fmt.Printf("c-b span is %v\n", cbSpan) // Prints 8
    fmt.Printf("d-c span is %v\n", dcSpan) // Prints 8
}


去游乐场,go1.20 - https://go.dev/play/p/BJIVC1cQQoT

去游乐场,去开发 - https://go.dev/play/p/BJIVC1cQQoT?v=gotip

问题是:

  1. 为什么打印24?剩下的16个字节是什么占用的? (考虑到
    a
    在 64 位机器上占用 8 个字节)
  2. 为什么 Go Playground 上的结果是随机的?
  3. 我们如何知道什么占用了其他 16 个字节?我想这可以通过检查汇编代码来完成。还有其他方法吗?
go pointers
1个回答
1
投票

堆分配取决于实现和运行时。


x.go

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    a := 7
    b := 8
    c := 9
    d := 10
    fmt.Printf("a's address is %v\n", &a)
    fmt.Printf("b's address is %v\n", &b)
    fmt.Printf("c's address is %v\n", &c)
    fmt.Printf("d's address is %v\n", &d)

    baSpan := uintptr(unsafe.Pointer(&b)) - uintptr(unsafe.Pointer(&a))
    cbSpan := uintptr(unsafe.Pointer(&c)) - uintptr(unsafe.Pointer(&b))
    dcSpan := uintptr(unsafe.Pointer(&d)) - uintptr(unsafe.Pointer(&c))

    fmt.Printf("b-a span is %v\n", baSpan)
    fmt.Printf("c-b span is %v\n", cbSpan) 
    fmt.Printf("d-c span is %v\n", dcSpan) 
}

./x.go:9:2: moved to heap: a
./x.go:10:2: moved to heap: b
./x.go:11:2: moved to heap: c
./x.go:12:2: moved to heap: d

go1.20 version && go1.20 build -gcflags='-m' x.go && ./x
go version go1.20.7 linux/amd64
a's address is 0xc000018130
b's address is 0xc000018138
c's address is 0xc000018140
d's address is 0xc000018148
b-a span is 8
c-b span is 8
d-c span is 8

go1.21 version && go1.21 build -gcflags='-m' x.go && ./x
go version go1.21rc4 linux/amd64
a's address is 0xc00009c010
b's address is 0xc00009c018
c's address is 0xc00009c020
d's address is 0xc00009c028
b-a span is 8
c-b span is 8
d-c span is 8

go version && go build -gcflags='-m' x.go && ./x
go version devel go1.22-4e728e5121 Mon Aug 7 16:07:50 2023 +0000 X:loopvar linux/amd64
a's address is 0xc00009c010
b's address is 0xc00009c018
c's address is 0xc00009c020
d's address is 0xc00009c028
b-a span is 8
c-b span is 8
d-c span is 8

https://go.dev/play/p/HeAMYeBG1_o?v=go1.20

a's address is 0xc0000b2000
b's address is 0xc0000b2008
c's address is 0xc0000b2010
d's address is 0xc0000b2018
b-a span is 8
c-b span is 8
d-c span is 8

https://go.dev/play/p/HeAMYeBG1_o?v=gotip

a's address is 0xc000012028
b's address is 0xc000012040
c's address is 0xc000012048
d's address is 0xc000012050
b-a span is 24
c-b span is 8
d-c span is 8

© www.soinside.com 2019 - 2024. All rights reserved.