Memory 当包含分配的变量被重新分配时,分配会发生什么变化?

Memory 当包含分配的变量被重新分配时,分配会发生什么变化?,memory,memory-management,memory-leaks,scope,rust,Memory,Memory Management,Memory Leaks,Scope,Rust,我很确定这有一个专门的名字,但我不知道它是什么 当你有一个指针停止指向一个有效的对象时,那就是一个悬空的指针,但是对于一个没有引用的对象,特别是在Rust中,又会怎么样呢 以以下代码为例: { let mut v: Vec<u32> = vec![1, 2, 3]; v = Vec::new(); v.push(0); } { 让mut v:Vec=Vec![1,2,3]; v=Vec::new(); v、 推(0); } 当v被重新分配给一个全新的向量

我很确定这有一个专门的名字,但我不知道它是什么

当你有一个指针停止指向一个有效的对象时,那就是一个悬空的指针,但是对于一个没有引用的对象,特别是在Rust中,又会怎么样呢

以以下代码为例:

{ 
    let mut v: Vec<u32> = vec![1, 2, 3];
    v = Vec::new();
    v.push(0);
}
{
让mut v:Vec=Vec![1,2,3];
v=Vec::new();
v、 推(0);
}

v
被重新分配给一个全新的向量时,旧向量会发生什么变化?在C/C++中,这是内存泄漏的起源,因为没有人会释放内存,而您也不再有办法这样做。然而,在Rust中,当退出一个作用域时会发生各种各样的魔法(因此示例代码中出现了
{}

从逻辑的角度来看,由于Rust没有GC,这意味着向量只会留在内存中,直到进程终止,当超出范围时扫描无法访问的对象会影响实际的GC,但我对Rust内部的了解还不够,无法做出这些猜测(尽管我想在某个时候这样做)

上述代码中到底发生了什么?是一个内存泄漏,你必须注意,就像C/C++中的< < /P> < P>锈(就像C++)一样,使用RAII来处理这个问题。需要销毁的类型实现了<代码>滴/代码>特性(C++中,它们有析构函数),当变量超出范围时,它自动调用。 锈迹斑斑:

{
    let a = foo();
    a = b; // `b` is moved to `a`,
           // the previous value of `a` is dropped, which frees memory
} // `a` goes out of scope, it is dropped, which frees memory
在C++中:

{
自动a=foo();
a=b;//`=`本质上是一个函数调用,
//但是一个适当的`=`实现应该正确地处理内存
}//`a`超出范围,调用其析构函数,释放内存

在RISE或C++中正确实现的类型,没有内存泄漏。 另一方面,C没有这样的概念,内存必须显式释放。

< P>锈迹(就像C++)使用RAII来处理这个问题。需要销毁的类型实现<代码>滴/代码>特性(C++中,它们有析构函数),当变量超出范围时自动调用。 锈迹斑斑:

{
    let a = foo();
    a = b; // `b` is moved to `a`,
           // the previous value of `a` is dropped, which frees memory
} // `a` goes out of scope, it is dropped, which frees memory
在C++中:

{
自动a=foo();
a=b;//`=`本质上是一个函数调用,
//但是一个适当的`=`实现应该正确地处理内存
}//`a`超出范围,调用其析构函数,释放内存

在RISE或C++中正确实现的类型,没有内存泄漏。


另一方面,C没有这样的概念,内存总是需要显式释放。

“在C/C++中,这就是内存泄漏的起源,因为没有人会释放内存,而你也不再有办法这样做。”在C++<代码> vector:Value=< /Cord>将释放旧内存,因此不会有泄漏。在C++中没有向量,并且不能简单地分配给数组,所以你不能编写这样的代码。一个正确的实现<代码>运算符=/COD>应该正确地处理内存。如果没有,就离开这个类型。直接使用<代码>新建< /COD>或断线,在C++中自行清除。为了创建内存泄漏,您必须使用原始指针来动态分配内存。一旦您意识到这一点并试图在生锈中执行同样的操作,您会发现RIST不允许您触摸<代码>未安全< /COD>块的原始指针。ggested duplicate target演示了隐藏,而不是覆盖。这种情况下的行为不同(比较和)@trentcl在您的第二个示例中(我相信它代表了隐藏)——看起来内存一直保存在堆栈上(没有释放),直到作用域结束,如中所示。因此,如果运行大循环,这种方法可能会积累大量内存“临时内存泄漏”,对吗?“在C/C++中,这就是内存泄漏的起源,因为没有人会释放内存,而您也不再有办法这样做。"在C++<代码> vector:Value=< /Cord>将释放旧内存,因此不会有泄漏。在C++中没有向量,并且不能简单地分配给数组,所以你不能编写这样的代码。一个正确的实现<代码>运算符=/COD>应该正确地处理内存。如果没有,就离开这个类型。直接使用<代码>新建< /COD>或断线,在C++中自行清除。为了创建内存泄漏,您必须使用原始指针来动态分配内存。一旦您意识到这一点并试图在生锈中执行同样的操作,您会发现RIST不允许您触摸<代码>未安全< /COD>块的原始指针。ggested duplicate target演示了隐藏,而不是覆盖。这种情况下的行为不同(比较和)@trentcl在您的第二个示例中(我相信它代表了隐藏)——看起来内存一直保存在堆栈上(没有释放),直到作用域结束,如中所示。因此,如果运行大循环,这种方法可能会积累大量内存“临时内存泄漏",是吗?我明白了,这是有道理的!我在这里讲的是直觉,但我想你所说的,加上Rust的所有权概念,以及编译器在指针悬空的情况下会对你咆哮,这在很大程度上保证了内存的安全性。但是,如果变量是顶级的呢?就像
main功能?意味着只有当程序运行时,它才会超出范围terminates@RaresDima
a
的旧值在分配新值之前被删除,与
a
的范围无关。这个答案有点不完整,因为它只提到了
drop()
当变量超出范围时被调用。Rust编译器在许多其他地方插入隐式删除,例如,就在赋值之前,或者如果一个变量只在一个
if
分支中移出,它会隐式删除到另一个
if
分支中。甚至有编译器无法解决的情况是的,所以