C++:内存泄漏

Posted

技术标签:

【中文标题】C++:内存泄漏【英文标题】:C++: memory leaks 【发布时间】:2010-11-11 07:58:32 【问题描述】:

问题:当变量n取什么值时,下面的代码会导致内存泄漏?

代码如下:


int* Bar(int n)

  if (n == 1)
    throw "exception";
  return new int[n];


void Foo(int n)

  int *a = Bar(n);
  if (n <= 2)
    return;
  delete[] a;

很明显,如果 n 为 2 将是内存泄漏。 如果 n 为 0,则可能会 是内存泄漏(根据 C++ new int[0] -- will it allocate memory?)

从 5.3.4/7 开始

当表达式的值在一个 direct-new-declarator 为零,则 调用分配函数 分配一个没有元素的数组。

从 3.7.3.1/2 开始

取消引用指针的效果 作为对零大小的请求返回的是 未定义。

还有

即使空间大小 请求 [by new] 为零,则 请求可能会失败。

这意味着你可以做到,但你可以 不合法(以明确的方式 跨所有平台)取消引用 你得到的记忆——你只能 将它传递给数组删除 - 你 应该删除它。

这是一个有趣的脚注(即 不是标准的规范部分, 但包括用于说明性目的) 附在句子的后面 3.7.3.1/2

[32.目的是让运营商 new() 可通过调用实现 malloc() 或 calloc(),所以规则是 基本相同。 C++ 不同 从 C 中要求零请求到 返回一个非空指针。]

如果 n 为 1,我们得到:

int *a = Bar(1) 和 Bar(1) 抛出异常。它会是变量a的构造函数中的异常吗?而且会不会造成内存泄露?

【问题讨论】:

这是一个很好的阅读:research.att.com/~bs/bs_faq2.html#finally Bar 中的 if 语句是否应该围绕以下两行,或者只是 throw 语句? 【参考方案1】:

如果 a == 0 或 a == 2,它可能会导致它们。

如果 a == 1 则抛出异常并且不分配内存。如果大于 2 的内存同时被分配和释放。

如果 a == 0 必须分配内存,因为不允许 new 返回空指针。您必须使用 delete[] 释放分配的内存。

如果分配了 a == 2 内存并且函数返回。这是明显的泄漏。

【讨论】:

如果(n @Clement H:阅读Sharptooth的回答,你只是在重复他写的东西(甚至有点不正确,因为你忽略了抛出的异常)。 @Clement : Sharptooth 的意思和你说的一样。只是他考虑了正值和 【参考方案2】: 如果 n 2 你会调用 delete - 没有内存泄漏。

【讨论】:

if n 是的,理论上你是可以的。但很可能没有这么多的可用内存。【参考方案3】:

不,如果我正确理解您的问题,bar 函数将抛出异常,而 Foo 函数实际上永远不会捕获它,这意味着它也会从该函数中传递出去。但是不,它不应该导致内存泄漏,因为你在分配之前就抛出了。

【讨论】:

这不是 Python,尽管错误的缩进使它看起来像那样。只有n==1才会抛出,否则会分配内存。 是的,但他询问是否使用参数 1 调用 Bar 会引发异常。【参考方案4】:

您的评估大部分是正确的 - n = 2 会导致内存泄漏,n = 0 理论上会导致内存泄漏 - n = 1 会引发异常(因此永远不会执行 new int),因此不会发生内存泄漏。

n > 2 的任何值都不会导致内存泄漏。

现在如果 n

【讨论】:

【参考方案5】:

由于抛出的异常没有捕获器,它将继续进行并返回。 但是由于我们声明为整数指针,如果您将“n”作为零发送,则会创建一个默认指针。您也可以检查指针的大小。但这不会导致任何内存泄漏。背后的原因,当你做一个返回时,因为它是一个整数指针并且是一个局部变量,默认情况下会释放所占用的内存。 所以,在你提到的情况下,不会发生内存泄漏。

【讨论】:

【参考方案6】:

是的,02 会导致内存泄漏。


另外,像这样管理动态内存也是非常糟糕的做法。 在 C++ 上,创建一个管理内存的类是更自然/更好的方法(例如,在构造函数中它分配一些内存,而在析构函数中它释放它)。这将更无泄漏和更安全

【讨论】:

以上是关于C++:内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

C++:内存泄漏

C++内存泄漏检测工具

C++调试内存泄漏

C++调试内存泄漏

C++调试内存泄漏

Windows 7 上的 C++ 内存泄漏