栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么指向局部变量的指针转义到堆?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么指向局部变量的指针转义到堆?

简化您的示例。用进行分析

-gcflags='-m -m'

范例1

package mainfunc main() {    var v int    s := make([]*int, 0)    s = append(s, &v) // &v escapes to heap}

输出:

$ go versiongo version devel +df8c2b905b Tue Mar 6 06:13:17 2018 +0000 linux/amd64$ go run -gcflags='-m -m' esc.go# command-line-arguments./esc.go:3:6: can inline main as: func() { var v int; v = <N>; s := make([]*int, 0); s = append(s, &v) }./esc.go:6:16: &v escapes to heap./esc.go:6:16:  from append(s, &v) (appended to slice) at ./esc.go:6:12./esc.go:4:6: moved to heap: v./esc.go:5:11: main make([]*int, 0) does not escape$

转义分析确定是否有任何对值的引用转义声明该值的函数。

v
在函数中声明的对变量的引用
main
作为函数的参数进行转义
append
&vescapes to heap from append(s, &v)
moved to heap: v


范例2

package mainfunc main() {    var v int    lc := 1    s := make([]*int, lc)    s[0] = &v}$ go run -gcflags='-m -m' esc2.go./esc2.go:3:6: can inline main as: func() { var v int; v = <N>; lc := 1; s := make([]*int, lc); s[0] = &v }./esc2.go:6:11: make([]*int, lc) escapes to heap./esc2.go:6:11:     from make([]*int, lc) (too large for stack) at ./esc2.go:6:11./esc2.go:7:9: &v escapes to heap./esc2.go:7:9:  from s[0] (slice-element-equals) at ./esc2.go:7:7./esc2.go:4:6: moved to heap: v$

type slice struct {    array unsafe.Pointer    len   int    cap   int}

make
切片返回切片描述符
struct
(指向基础数组,长度和容量的指针)并分配基础切片元素数组。底层数组通常在堆上分配:
make([]*int,lc) escapes to heap from make([]*int, lc)

s[0] = &v
存储对变量的引用
v
&v
)在堆上底层阵列中:
&v escapes to heap from s[0] (slice-element-equals)
moved to heap: v
。函数结束并回收其堆栈之后,引用将保留在堆上,直到对基础数组进行垃圾回收为止。

如果

make
切片容量是一个小的(编译时)常数,则
make([]*int,1)
在您的示例中,基础数组可能会分配在堆栈上。但是,转义分析没有考虑到这一点。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/436269.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号