存储指向堆栈值的指针(Golang) [英] Storing a pointer to a stack value (Golang)

查看:56
本文介绍了存储指向堆栈值的指针(Golang)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Go中尝试一个实验,以查看如果将指针存储在堆栈上,然后在原始变量离开作用域之后访问该变量,会发生什么情况.

I'm trying an experiment in Go, to see what happens if I store a pointer to a variable on the stack, and then access that variable after the original variable has left scope.

package main

import "fmt"

var p chan bool;

// a temp struct
type v struct {
    a int
}

func another_thread(vx *v) {
    // this code should be executed after a() returns so vx should be a pointer to a value that's no longer on the stack
    fmt.Printf("another_thread(): %p\n", vx);
    vx.a = 4 // am I updating a dangling pointer that may have unintentional side effects??
    fmt.Println(" - ", vx.a);
    p<-true;
}

func update_v(vx *v) {
    vx.a = 3;

    fmt.Printf("update_v(): %p\n", vx);

    go another_thread(vx)
}

func alloc_on_stack() {
    // allocate v1 on the stack
    var v1 v
    v1.a = 1

    fmt.Printf("alloc_on_stack(): %p\n", &v1);

    // pass a pointer to v1 on the stack
    update_v(&v1)

    // print '3' to prove byref actually took it by reference
    fmt.Println(" - ", v1.a);

    // when the function returns, v1 should be popped off the stack
}

func main() {
    p = make(chan bool)
    alloc_on_stack();
    fmt.Println("outside of alloc_on_stack, waiting");
    <-p;
    fmt.Println("done");
}

在alloc_on_stack中,v1作为局部变量存储在堆栈中.我将指向v1的指针传递给update_v,该指针将其传递给another_thread.直到alloc_on_stack完成后,other_thread才会执行.

In alloc_on_stack, v1 is stored as a local variable on the stack. I pass a pointer to v1 to update_v, which passes it to another_thread. By another_thread doesn't execute until after alloc_on_stack finishes.

但是,当我运行该代码时,我没有得到任何错误,而是看到了:

Yet, when I run that code, I don't get any errors, instead I see this:

alloc_on_stack(): 0x1043617c
update_v(): 0x1043617c
 -  3
outside of alloc_on_stack, waiting
another_thread(): 0x1043617c
 -  4
done

vx another_thread内不应该是一个悬空指针吗?

Shouldn't vx inside another_thread be a dangling pointer?

推荐答案

不是.Go编译器检测到您正在使用局部变量的地址,并将其保留到所有对它的引用消失为止.从此以后,就可以对变量进行垃圾收集了.

Nope. The Go compiler detects that you are taking the address of a local variable, and keeps it around until all references to it are gone. From then on, the variable can be garbage collected.

这就是为什么不允许这样的事情,甚至是惯用的原因的原因:

This is why stuff like this isn't just allowed, it's even idiomatic:

func foo() *Bar {
  return &Bar{42, "frob"}
}

这篇关于存储指向堆栈值的指针(Golang)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆