golang 结构体里面有指针类型的字段, 怎么计算其偏移量?

2022-06-23 22:34:38 +08:00
 jeesk
  1. 结构体含有指针
type Stu struct {
  pkg *Pkg
  age int 
}

type Pkg struct {

}
  1. pkg 字段是个私有字段, 没有办法通过 unsafe.Offsetof() 拿到,只能通过 unsafe.SizeOf() , 但是这个 pkg 字段是个指针? 这个时候要怎么计算偏移量才能获取 age 的指针, 然后拿到 age 的值?
  2. 还是上面的例子,结构体里面有匿名字段
type Stu struct {
  Pkg
  age int 
}

这种情况还能通过 unsafe.SizeOf(&Pkg{}) , 这种办法能拿到 pkg 的偏移量吗?

上面两种情况要么我自己拿到的不对, 要么无处下手, 头大了。

最近被 golang 再次折磨了。

2166 次点击
所在节点    Go 编程语言
9 条回复
chenxiankong
2022-06-23 23:10:33 +08:00
```
package main

import (
"fmt"
"unsafe"
)

func main() {
stu := &Stu{
pkg: &Pkg{},
age: 1,
}
age := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(stu))+unsafe.Offsetof(stu.age)))
fmt.Println(*age)
}

type Stu struct {
pkg *Pkg
age int
}

type Pkg struct {

}
```
验证可行
jeesk
2022-06-23 23:26:01 +08:00
@chenxiankong 不我是没有办法访问到字段的,我能直接访问 stu.age ? 还用指针干毛线呀? 这里的*Pkg 的偏移量怎么算?
jeesk
2022-06-23 23:26:28 +08:00
@chenxiankong 我是没有办法访问到字段的,我能直接访问 stu.age ? 还用指针干毛线呀? 这里的*Pkg 的偏移量怎么算?
chenxiankong
2022-06-23 23:33:52 +08:00
@jeesk 64 位机器指针字段都是 8 字节,32 位是 4 字节,严谨一点可以通过判断机器环境 来选择取 4 还是 8
lujjjh
2022-06-24 00:17:02 +08:00
不知道什么场景需要访问其他包结构体里的私有字段,有一种比较 tricky 的方式是直接把结构体的(部分)定义复制过来。

比如获取 time.Time 结构体里的 ext 字段:

https://gist.github.com/lujjjh/e92cb9904f8ec8bb42829cea0f6c2400

当然,风险是如果以后这个结构体发生变化了,可能就没法正常运行了。
0o0O0o0O0o
2022-06-24 00:34:56 +08:00
如果是无源码的 hack 场景,关键词:

data structure alignment
memory layouts
jeesk
2022-06-24 01:16:21 +08:00
@chenxiankong 正解 。 已经拿到了。
tj3u2l
2022-06-24 02:36:38 +08:00
type Stu struct {
pkg *pkg
age int
}

type pkg struct {
test string
}

func main() {
s := Stu{pkg: &pkg{test: "123"}, age: 10}
fmt.Println(unsafe.Sizeof(new(pkg)))
fmt.Println(*(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + unsafe.Sizeof(new(pkg)))))
}

就 Sizeof 的参数填 pkg 的指针就好了
zone10
2022-06-24 09:51:01 +08:00
golang 有反射 reflect 这个库, 应该可以像 Python 那样根据字段名拿私有字段, 用偏移量拿说真的不是一个好习惯, 你这个例子前面只有一个字段问题还没那么大, 要是整多几个要字节对齐怎么办, 就算你全考虑到了知道怎么对齐拿到正确的字段, 这种根据编译器实现的编程方式都是坏习惯

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/861769

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX