0°

(整合多篇文章)C++悬垂指针、野指针、内存泄漏和垃圾回收机制

C++的内存回收机制

当我们使用new为一个对象分配了空间之后,在这个对象结束使用之后,我们必须人为的去释放这块内存(delete)

Java的内存回收机制

 当用new 创建一个Java对象时,它可以存活于作用域之外。所以在上述代码中,引用 str(str为String对象“HelloWorld!” 的引用) 在作用域终点就消失了。然而,str指向的String对象仍继续占用内存 堆空间 。在这一段代码中,我们无法在这个作用域之后访问这个对象,因为对它唯一的引用已经超出作用域的范围。(注:如果想使用 我们需要传递或者复制这个引用)

事实证明,由new创建的对象,只要你需要,就会一直保存下去。这样,许多C++编程问题在Java中就会完全消失。在C++中,你不仅需要去确保对象的保留时间与你所需要的这些对象的的时间一样长,而且必须在使用完之后将其销毁。

但是,如果Java让对象继续存在,那么靠什么才能防止这些对象填满内存空间,进而阻塞程序呢? 这正是C++里可能发生的问题。同时这也是Java的神奇所在。Java是这样处理的。

在Java 中有一个 **垃圾回收器 **,用来监视用new创建的所有对象,并辨别那些不会再被引用的对象。随后,释放这些对象的内存空间,以便供其他新的对象使用。也就是说,程序员们根本不必担心内存回收的问题。只需要创建对象,一旦不需要了,他们就会由垃圾回收器自动回收,内存就会自动得到释放。这样做就消除了这类编程问题(“内存泄漏问题”)。

这种解决方法大大简化了编程的难度。

悬垂指针

在许多编程语言中(比如C),显示地从内存中删除一个对象或者返回时通过销毁栈帧,并不会改变相关的指针的值。该指针仍旧指向内存中相同的位置,即使引用已经被删除,现在可能已经挪作他用。

如果操作系统能够侦测运行时的指向空指针的引用,一个方案是在内部快消失之前给dp赋为0(NULL)。另一个方案是保证dp在没有被初始化之前不再被使用。

另一个常见原因是混用 
malloc() 和 
free():当一个指针指向的内存被释放后就会变成悬垂指针。正如上个例子,可以避免这个问题的一种方法是在释放它的引用后把指针重置为NULL。

一个很常见的失误是返回一个栈分配的局部变量:一旦调用的函数返回了,分配给这些变量的空间被回收,此时它们拥有的是“垃圾值”。

野指针

野指针的产生是由于在首次使用之前没有进行必要的初始化。因此,严格地说,在编程语言中的所有为初始化的指针都是野指针。

在更多结构化的解决方案中,一种流行的避免悬垂指针的技术是使用
智能指针。一个智能指针通常使用引用技术来收回对象。还有些技术包括 tombstones 方法和 locks-and-keys 方法。

另一个方法是使用 Boehm 垃圾收集器,一种保守的垃圾收集器,取代C和C++中的标准内存分配函数。此法通过禁止内存释放函数来完全消除悬垂指针引发的错误,通过收集垃圾来回收对象。

像Java语言,悬垂指针这样的错误是不会发生的,因为Java中没有明确地重新分配内存的机制。而且垃圾回收器只会在对象的引用数为0时重新分配内存。

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!