为什么动态内存超出范围时不会被清除

时间:2014-01-28 14:46:36

标签: c++ memory-management memory-leaks

我刚开始玩C ++(熟悉其他语言),我想知道一些事情。

在使用new创建动态大小的数组时,为什么它在超出范围时不会被删除,但是具有固定大小的数组会被删除?

例如,使用以下代码:

int foo()
{
    int baz[5]; // Gets removed out of scope
    int *bar = new int[5]; // Does not get removed, becomes a leak
}

由于baz和bar都是指向数组开头的指针,因此“运行时环境”不能应用相同的技术(检测某些内容是否超出范围,并在删除时将其删除)固定大小为动态大小?

它不能做这样的事情有什么不同。

5 个答案:

答案 0 :(得分:7)

  

为什么动态内存超出范围时不会被清除

因为动态内存的目的是分配超出范围的结尾。当您需要在一个范围内分配内存,然后在另一个范围内使用和取消分配内存时,将使用动态内存。

答案 1 :(得分:2)

  

创建动态大小的数组时,例如使用new,为什么不删除它

因为这是new的主要目的:允许你控制对象何时被销毁,这可能超出了它的创建范围。

(在其他情况下也需要动态分配 - 创建大小或对象,其类型在编译时是未知的,或者对于堆栈而言可能太大 - 因为该语言不直接提供单独的机制在这种情况下,您可以使用智能指针或容器将对象的生命周期绑定到范围。)

  

由于bazbar都是指向数组开头的指针

不,他们不是。 baz是一个数组;当它超出范围时它会被销毁。 bar是指向数组的指针;它被摧毁了,但它指向的阵列不是。

  

“运行时环境”不能应用相同的技术

没有。通常,无法知道指针是否指向动态对象。即使有,也没有办法知道是否有其他引用它应该在该指针被销毁后保持有效。

答案 2 :(得分:1)

因为固定大小的数组是在函数的堆栈中分配的,而动态的数组是在程序的堆中分配的。函数堆栈是用于存储局部变量的内存空间。到达功能结束时,堆栈自动释放。堆是不同的,一旦程序关闭它就是免费的。

答案 3 :(得分:1)

动态内存在范围结束时不会自动释放,因为动态内存的目的是拥有更多控制权。您可能希望在分配它的同一范围的末尾解除分配,但您可能想要在其他地方解除分配 - 这一切都取决于您的程序的设计。

答案 4 :(得分:1)

超出范围的事情是指向内存的一个指针,而不是内存本身(它没有范围,只有生命周期)。你不想在任何指向它的指针死亡时释放内存 - 实际上你总是希望分发临时指针(例如将它们传递给其他函数),从函数返回指针,在其他一些地方存储指针的副本等等。

换句话说,在使用动态分配的内存的过程中,您必须创建并销毁许多指向该内存的指针。您不希望大多数指针使用它们获取内存,只应使用 last 指针来释放内存。任何早些时候,你会得到悬垂的指针;任何以后你都没有指针,根本就不能释放它。

方式将内存管理连接到指针的生命周期,包括转移所有权的能力:返回指针,将其从一个变量移动到另一个变量等等。这是一个...称智能指针,特别是unique_ptr

但是,这不适合作为 only 指针类型,您仍然需要所有上述用途的非拥有指针(在不释放内存的情况下分发临时引用)。此外,据我所知,这个想法(或者至少是它主流的采用)早于C ++。它肯定早于C,这意味着即使Bjarne天生就拥有智能指针,C ++也需要保留原始指针。

相关问题