内容简介:在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不保证地址一定是有效的,当然还有其它的原因,有时间再验证分享。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 表单正则验证及文件上传验证功能
- angular 实现同步验证器跨字段验证
- Spring Security验证流程剖析及自定义验证方法
- TensorFlow 推出数据验证函数库 TFDV,用于分析和验证
- TensorFlow 推出数据验证函数库 TFDV,用于分析和验证
- 滑动验证码的原理并利用 Vue 实现滑动验证码
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Servlet与JSP核心编程
[美]Marty Hall、Larry Brown、Yaakov Chalkin / 胡书敏 / 2009-6 / 68.00元
《Servlet与JSP核心编程(第2卷 第2版)》在第l卷的基础上,广泛涉及自定义标签库、过滤器、声明式安全、JSTL和Struts等主题,并沿袭深受读者喜爱的写作风格,通过完整、有效、资料丰富的程序来演绎目前最流行的技术和最佳实践。Java EE已经成为电子商务网站、动态网站和Web应用与服务开发的首选,作为这一平台的基础,servlet与JSP的重要性日益突出,并在极短的时间内得以迅速普及。......一起来看看 《Servlet与JSP核心编程》 这本书的介绍吧!