- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
第
GO中什么情况会使用变量逃逸
目录C程序GO程序GO的逃逸是啥样子的?你知道GO中什么情况会变量逃逸吗?首先我们先来看看什么是变量逃逸
Go语言将这个以前我们写C/C++时候需要做的内存规划和分配,全部整合到了GO的编译器中,GO中将这个称为变量逃逸
GO通过编译器分析代码的特征和代码的生命周期,决定应该使用堆还是栈来进行内存分配
C代码和GO代码对比哪个会崩溃?
咱们写一个简单的例子,在C里面内存分配到栈上面还是堆上面是一个很明确的事情
例如
函数中的变量是分配在栈上面,会随着该函数调用完毕后随之销毁掉
程序员自己malloc开辟的内存是在堆上面,需要程序员自己去释放
那么问题来了:
如果我们将某一个函数中的局部变量的地址(全篇以局部变量为例),作为该函数的返回值,最终在函数外部去访问这个局部变量的地址,是否会出错呢?一起来看看吧
C程序
test.c
int*get_res(intnum){
inttmp=num+10;
returntmp;
intmain(){
int*res=get_res(80);
printf(%d--%p\n,*res,res);
上面写了一个简单的C代码,获取传入数据并+10得到的结果
#gcctest.c-otest
test.c:Infunction‘get_res:
test.c:7:12:warning:functionreturnsaddressoflocalvariable[-Wreturn-local-addr]
returntmp;
^~~~
#./test
Segmentationfault
这里可以看出编译程序,报了warning了,不过不影响程序的编译,这个warning报错信息是因为我们返回了临时变量的地址,C编译器检测到了,给我们抛出了一个warning
执行编译的程序后,崩溃了,熟悉C的小伙伴一点都不惊慌,他们不会写出这种代码
出现段错误的原因很明显,上面有说到,是因为外部访问了局部变量的地址,外部访问的时候,此时这个局部变量已经被销毁了,此时外部访问的这个指针,属于野指针,因此出现程序崩溃
GO程序
go程序的逻辑和上面C程序的逻辑一模一样,那么我们看看是否会出现程序崩溃呢
funcgetRes(numint)*int{
tmp:=num+10
returntmp
funcmain(){
res:=getRes(80)
fmt.Printf(%d--%p\n,*res,res)
执行上述代码,查看效果
#gorunmain.go
90--0xc420018078
熟悉go语言的小伙伴看到这里心中也毫无波澜,程序正常执行,没有崩溃,因为他们知道原因,这个现象属于变量逃逸
那么我们一起来看看GO为什么会这样做,是如何做的呢?
GO的逃逸是啥样子的?
上面有说到GO不会像C/C++一样需要程序员自己去关心内存分配,是期望GO程序员更多的关注逻辑
因此内存分配这一块,GO编译器都做的妥妥的,一个变量是分配在栈上面还是堆上面,不是简单的看一个变量是局部变量就分配到栈上,这个是根据具体的使用的,有时候它也会被分配到堆上面
当我们发现本应该分配在栈上面的变量,却分配在堆上面了,说明发生了逃逸
开始探究和验证
我们可以尝试写一个简单的demo,还是将局部变量的地址返回到外部去,外部来访问这个局部变量的地址
funcgetRes(tmpint)*int{
vart1int=1
vart2int=2
vart3int=3
println(tmp,t1,t2,t3)
returnt2
funcmain(){
res:=getRes(80)
println(*res,res)
执行上述代码查看效果
0xc420045f500xc420045f680xc420045f600xc420045f58
20xc420045f60
通过上面的将变量地址打印出来貌似没有看出上面端倪,地址是也是连续的
那么我们使用go提供的工
文档评论(0)