go - 为什么Go经常将字符串数据存储在未对齐的地址处

标签 go memory-management memory-layout

我读过很多关于内存中值对齐的重要性的文章,因为访问未对齐的地址可能会减慢操作速度,或者根本无法工作,具体取决于 CPU 架构(引用文献 https://syslog.ravelin.com/go-and-memory-layout-6ef30c730d51 )。但后来我注意到,在 Go 中实例化一个简单的字符串时,它经常将字符串值存储在未对齐的地址处。

通过运行以下代码可以看到这一点:

package main

import (
    "fmt"
    "unsafe"
    "reflect"
)

func main() {
    testString:= "testString"

    fmt.Println(fmt.Sprintf("Data is at address %d", ((*reflect.StringHeader)(unsafe.Pointer(&testString))).Data))
}

https://play.golang.org/p/d1eX0nP3AgV 上运行时我不断得到:

Data is at address 1140305

1140305 显然不能被 48 整除。

有人可以解释一下为什么 Go 将该值存储在一个未对齐的地址吗?使用对齐的不是更好吗?这只是为了不浪费空间,同时依赖现代 CPU 可以处理它的事实。还是因为虚拟内存层抽象了物理内存地址,而实际上物理地址是正确对齐的?

最佳答案

你是对的,32 位值(例如整数)应该在 4 字节边界上对齐,否则访问它可能需要两次内存访问而不是一次。类似地,64 位值应在 8 字节边界上对齐,但在 32 位系统(即到内存的 32 条数据线)中,4 字节边界就足够了,因为无论如何都需要两次内存访问。

但是,Go 中的字符串数据实际上是一个字节数组,因此没有对齐要求。如果你在 C 中打印字符串的地址,你会发现同样的事情(出于效率原因,它非常关心对齐)。

一旦你理解了对齐,它就相当简单,但需要大量解释。我在 http://devmethodologies.blogspot.com/2013/04/alignment-and-pragma-pack.html 上写了关于它(针对 C)的文章。 .

关于go - 为什么Go经常将字符串数据存储在未对齐的地址处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60572169/

相关文章:

go命令访问自签名证书

go - 当我尝试运行 main.go 时,我得到 cgo : exec gcc: exec: "gcc": executable file not found in $PATH

c++ - 哪个指针赋值更好(C++)

linker - SEGMENT_START ("text-segment", 0x400000) 代表什么?

optimization - 约束单目标优化

google-app-engine - Appengine 搜索语言

c++ - 如何强制 Windows 向所有应用程序发送 'LOW_MEMORY' 信号?

r - R中整数向量的大小

C++ 编译器可以将常量类数据从类中优化出来吗?

c - c中可以存在多少种指针值组合?