C C++中内存泄漏的原因

9
除了通常的分配内存后忘记释放之外,C和C++中出现内存泄漏的原因是什么?

3
前一晚喝了太多啤酒了吗? - kuroi neko
黑猫 - Adilet Usonov
8个回答

20

如果在分配内存和释放内存之间抛出异常,就会发生内存泄漏。

void f1() {
    int* ptr = new int;

    // do something which may throw an exception

    // we never get here if an exception is thrown
    delete ptr;
}

每次f1由于异常而终止时,将泄漏4个字节(假设int为4个字节)。


3
智能指针比原始指针(如int *)更“智能”的原因之一是,智能指针有析构函数可以在对象不再需要时自动释放内存。原始指针没有析构函数,需要手动管理内存,容易出现内存泄漏和悬空指针等问题。参考链接:https://dev59.com/GHVD5IYBdhLWcg3wDXF3 - HostileFork says dont trust SE

15

内存泄漏是在你分配了内存后,还没有释放它,同时你将永远无法释放它,因为你不能再访问它

例如,下面的代码会导致大小为sizeof(int)的内存泄漏:

int * a = malloc(sizeof(int)); //allocate memory
a = 0; //this will cause a memory leak

这会导致内存泄漏,因为现在我们将永远无法释放为a分配的内存。


6

当你没有释放一些其他资源时,例如没有在FILE*或其他库句柄上调用fclose,也可能会泄漏内存,因为它们可以分配对你的程序不直接可访问的内存缓冲区。


5
假设您创建了一个继承自其他没有虚析构函数的类的类。如果指向此类的指针的类型不是最派生类(如果使用抽象工厂,则通常会发生这种情况),则只会调用指针类型的析构函数,而您希望在最派生类析构函数中释放的任何内容都将泄漏。
这是非常常见的错误,有时很难发现。
无论如何,如果您想避免C++中的内存泄漏,请遵循以下规则:
- 更喜欢传递引用而不是指针 - 尽可能使用智能指针(参见:shared_ptr

当然,标准规定如果基类的析构函数不是虚函数,那么行为是未定义的。所以你正在进行一些危险的操作,内存泄漏只是其中最微不足道的问题。至于shared_ptr,它有时很有用,但还有更好的智能指针/容器适合日常使用。它肯定应该是最后的选择。 - Matthieu M.

2

如果没有deletenew,没有delete[]new[],没有freemalloc,将会导致内存泄漏。

说真的,还有什么需要解释的吗?


2

除了您提到的原因外,内存泄漏没有其他原因。


这个的反例是watson1180的回答。 - Cam
@Cam:我不这么认为,在watson1180的例子中,他忘记调用delete(尽管在代码中写下了)。 - Matthieu M.
@Matthieu:嗯...确实。不幸的是,我目前无法取消对beb0答案的踩。 - Cam
实际上,存在许多导致内存泄漏的原因。 - Raphael
1
另一方面,有一些非常糟糕构建和文档化不好的API,你不知道何时需要释放一些资源(因此从函数返回智能指针而不是裸指针始终是更可取的)。 - Raphael
显示剩余7条评论

1

我很惊讶没有人提到内存损坏。

我记得有一个情况,我们实现了一个简陋的固定大小块内存分配器,作为链表。

有个家伙搞砸了大小计算,导致复制数据超出最大块大小几个字节(当时指针只有2个字节长:))。然后它会用填充了零的垃圾覆盖下一个空闲块开头处的“下一个”链接。

这就导致断开了空闲块链。由于在那时刻其他软件部件维护了自己的指针指向它们正在使用的任何块,因此程序似乎运行得非常好。

但是当然,列表偶尔会短缺一些块,这个泄漏最终耗尽了自由块,导致应用程序挂起。


0
以下示例以伪代码编写,旨在展示内存泄漏如何发生及其影响,无需任何编程知识。该程序是一些非常简单的软件的一部分,旨在控制电梯。每当电梯内有人按下楼层按钮时,程序的这部分就会运行。
当按下按钮时:
  Get some memory, which will be used to remember the floor number
  Put the floor number into the memory
  Are we already on the target floor?
    If so, we have nothing to do: finished
    Otherwise:
      Wait until the lift is idle
      Go to the required floor
      Release the memory we used to remember the floor number

如果请求的楼层与电梯所在的楼层相同,则会发生内存泄漏;释放内存的条件将被跳过。每次出现这种情况时,都会泄漏更多的内存。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接