英文:
What happens to pointer to element when Go moves slice to another place in memory?
问题
我有以下代码:
package main
import "fmt"
func main() {
a := []int{1}
b := &a[0]
fmt.Println(a, &a[0], b, *b) // 输出 [1] 0xc00001c030 0xc00001c030 1
a = append(a, 1, 2, 3)
fmt.Println(a, &a[0], b, *b) // 输出 [1 1 2 3] 0xc000100020 0xc00001c030 1
}
首先,它创建了一个包含1个int的切片。它的长度为1,容量也为1。然后,我获取其第一个元素的指针,并在打印中获取其底层指针值。正如预期的那样,它正常工作。
然后,我向切片添加了3个元素,使得切片的容量增加,从而将其复制到内存中的另一个位置。之后,我打印了切片的第一个元素的地址(通过获取指针),该地址与b
中存储的地址不同。
然而,当我打印b
的底层值时,它也正常工作。我不明白为什么它能正常工作。据我所知,指向b
的第一个元素的切片被复制到内存中的另一个位置,因此它的先前内存必须已被释放。然而,它似乎仍然存在。
如果我们看一下映射,Golang甚至不允许我们通过键创建元素的指针,因为存在完全相同的问题-底层数据可能被移动到内存中的另一个位置。然而,对于切片来说,它完全正常工作。为什么会这样?它是如何工作的?内存没有被释放,是因为仍然有一个指向该内存的变量吗?它与映射有何不同?
英文:
I have the following code
package main
import "fmt"
func main() {
a := []int{1}
b := &a[0]
fmt.Println(a, &a[0], b, *b) // prints [1] 0xc00001c030 0xc00001c030 1
a = append(a, 1, 2, 3)
fmt.Println(a, &a[0], b, *b) // prints [1 1 2 3] 0xc000100020 0xc00001c030 1
}
First it creates a slice of 1 int. Its len is 1 and cap is also 1. Then I take a pointer to its first element and get the underlying pointer value in print. It works fine, as expected.
Than I add 3 more elements to the slice making go expand the capacity of the slice, thus copying it to another place in memory. After that I print the address (by taking a pointer) of the slice's first element which is now different from address stored in b
.
However, when I then print the underlying value of b
it also works fine. I don't understand why does it work. As far as I know the slice to which first element b
points to was copied to another place in memory, so its previous memory must have been released. However, it seems to still be there.
If we look on maps, golang doesn't even allow us to create pointers on element by key because of the exact same problem - underlying data can be moved to another place in memory. However, it works perfectly fine with slices. Why is it so? How does it really works? Is the memory not being freed because there still is a variable which points to this memory? How is it different from maps?
答案1
得分: 6
当Go将切片移动到内存中的另一个位置时,指向元素的指针会发生什么情况?
没有任何变化。
当我打印b
的底层值时,它也能正常工作。我不明白为什么会这样。
为什么它不能正常工作呢?
原始指向的内存位置仍然存在,没有改变。只要有任何东西(比如b
)仍然引用它,它就可以继续使用。一旦所有对该内存的引用都被移除(即超出作用域),垃圾回收器可能会允许其他东西使用它。
英文:
> What happens to pointer to element when Go moves slice to another place in memory?
Nothing.
> [W]hen I then print the underlying value of b
it also works fine. I don't understand why does it work.
Why wouldn't it work?
The memory location originally pointed to is still there, unaltered. And as long as anything (such as b
) still references it, it will remain usable. Once all references to that memory are removed (i.e. go out of scope), then the garbage collector may allow it to be used by something else.
答案2
得分: 1
当Go将切片移动到内存的另一个位置时,指向元素的指针会发生什么变化?
我相信当前的GC实现根本不会移动这样的对象,尽管规范允许这样做。除非你使用"unsafe"包,否则即使它移动了底层数据结构,你也不太可能遇到任何问题。
英文:
> What happens to pointer to element when Go moves slice to another
> place in memory?
I believe the current GC implementation do not move such objects at all, although the specifications allow for this to happen. Unless you use the "unsafe" package, you are unlikely to encounter any problems even if it did move the underlying data structure.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论