内容简介:在go中,uintptr不能持有对象,unsafe包不安全,但是我之前一直没有时间验证,今天写了段代码验证了一下。根据逃逸分析可以看出来f和f2这两个函数中的d变量分别分配在哪里:可以看出来在函数f中,d逃逸到堆上;但是在函数f2中,d没有发生逃逸,uintptr没有持有对象。
在 go 中,uintptr不能持有对象,unsafe包不安全,但是我之前一直没有时间验证,今天写了段代码验证了一下。
代码
package main
import (
"fmt"
"unsafe"
)
func main() {
a := f()
b := f2()
fmt.Println(a)
fmt.Println(b)
}
//go:noinline
func f() unsafe.Pointer {
d := 1
p := unsafe.Pointer(&d)
return p
}
//go:noinline
func f2() uintptr {
d := 1
p := uintptr(unsafe.Pointer(&d))
return p
}
逃逸分析
根据逃逸分析可以看出来f和f2这两个函数中的d变量分别分配在哪里:
编译参数方法
$ go build -gcflags '-m -m' unsafe.go
# command-line-arguments
./unsafe.go:16:6: cannot inline f: marked go:noinline
./unsafe.go:23:6: cannot inline f2: marked go:noinline
./unsafe.go:8:6: cannot inline main: function too complex: cost 260 exceeds budget 80
./unsafe.go:11:13: inlining call to fmt.Println func(...interface {}) (int, error) { return fmt.Fprintln(io.Writer(os.Stdout), fmt.a...) }
./unsafe.go:12:13: inlining call to fmt.Println func(...interface {}) (int, error) { return fmt.Fprintln(io.Writer(os.Stdout), fmt.a...) }
./unsafe.go:18:22: &d escapes to heap
./unsafe.go:18:22: from p (assigned) at ./unsafe.go:18:4
./unsafe.go:18:22: from ~r0 (return) at ./unsafe.go:19:2
./unsafe.go:17:2: moved to heap: d
./unsafe.go:25:30: f2 &d does not escape
./unsafe.go:11:13: a escapes to heap
./unsafe.go:11:13: from ~arg0 (assign-pair) at ./unsafe.go:11:13
./unsafe.go:11:13: io.Writer(os.Stdout) escapes to heap
./unsafe.go:11:13: from io.Writer(os.Stdout) (passed to call[argument escapes]) at ./unsafe.go:11:13
./unsafe.go:12:13: io.Writer(os.Stdout) escapes to heap
./unsafe.go:12:13: from io.Writer(os.Stdout) (passed to call[argument escapes]) at ./unsafe.go:12:13
./unsafe.go:12:13: b escapes to heap
./unsafe.go:12:13: from ~arg0 (assign-pair) at ./unsafe.go:12:13
./unsafe.go:12:13: from []interface {} literal (slice-literal-element) at ./unsafe.go:12:13
./unsafe.go:12:13: from fmt.a (assigned) at ./unsafe.go:12:13
./unsafe.go:12:13: from *fmt.a (indirection) at ./unsafe.go:12:13
./unsafe.go:12:13: from fmt.a (passed to call[argument content escapes]) at ./unsafe.go:12:13
./unsafe.go:11:13: main []interface {} literal does not escape
./unsafe.go:12:13: main []interface {} literal does not escape
<autogenerated>:1: os.(*File).close .this does not escape
可以看出来在函数f中,d逃逸到堆上;但是在函数f2中,d没有发生逃逸,uintptr没有持有对象。
汇编
再来看看汇编的结果:
$ go tool compile -S unsafe.go | grep unsafe.go:24 0x000e 00014 (unsafe.go:24) PCDATA $2, $0 0x000e 00014 (unsafe.go:24) PCDATA $0, $0 0x000e 00014 (unsafe.go:24) MOVQ $1, "".d(SP) $ go tool compile -S unsafe.go | grep unsafe.go:17 0x001d 00029 (unsafe.go:17) PCDATA $2, $1 0x001d 00029 (unsafe.go:17) PCDATA $0, $0 0x001d 00029 (unsafe.go:17) LEAQ type.int(SB), AX 0x0024 00036 (unsafe.go:17) PCDATA $2, $0 0x0024 00036 (unsafe.go:17) MOVQ AX, (SP) 0x0028 00040 (unsafe.go:17) CALL runtime.newobject(SB) 0x002d 00045 (unsafe.go:17) PCDATA $2, $1 0x002d 00045 (unsafe.go:17) MOVQ 8(SP), AX 0x0032 00050 (unsafe.go:17) MOVQ $1, (AX)
可以看出来,结果也是一样的,f中的d调用了newobject,但是f2中没有。
结论
所以为什么说unsafe包不安全呢,原因之一就是因为go不保证地址一定是有效的,当然还有其它的原因,有时间再验证分享。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Purely Functional Data Structures
Chris Okasaki / Cambridge University Press / 1999-6-13 / USD 49.99
Most books on data structures assume an imperative language such as C or C++. However, data structures for these languages do not always translate well to functional languages such as Standard ML, Ha......一起来看看 《Purely Functional Data Structures》 这本书的介绍吧!
HEX CMYK 转换工具
HEX CMYK 互转工具
HSV CMYK 转换工具
HSV CMYK互换工具