【问题标题】:Memory leak in this situation? Using new keyword over and over在这种情况下内存泄漏?一遍又一遍地使用新关键字
【发布时间】:2016-08-25 01:28:33
【问题描述】:

我对内存泄漏非常谨慎,所以我想我会对此进行验证。在以下示例中是否会出现内存泄漏?我的直觉告诉我是的。

class Handler        // Class definition
{public:
  ~Handler();
  int* ptrToInts;    
};

Handler::~Handler()  // Class destructor
{
  delete[] ptrToInts; 
}

Handler handler;     // Global object


void aFunction()
{
    handler.ptrToInts = new int[20];
}


int main()
{
  bool quit = false;

  while(!quit)
    {
      aFunction(); 
    }

  return 0;
}

ptrToInts 会在堆时间的单独内存中创建 20 个单独的新整数吗?

另外,另一个问题是,如果不是析构函数,动态分配的内存会被释放吗?好像类的生命周期就是程序的持续时间,它会清理所有“新”内存吗?

编辑:感谢您的回答。我问这个的原因是因为我试图绕过调用 new 和 delete 每次调用 WndProc 基本上是原始输入,这就是 MSDN 告诉你这样做的方式。看起来效率很低。

【问题讨论】:

  • 如果您不止一次执行newdelete[] 仅执行一次,那么是的,您有内存泄漏。它们需要保持平衡。
  • 使用工具(如valgrind.org)来告诉你你的程序是否(以及在哪里)有内存泄漏。
  • valgrind 不能在 MS Windows 平台上运行。

标签: c++ pointers memory memory-leaks heap-memory


【解决方案1】:

只有delete[] 释放由new 分配的内存。每次你使用new,你需要一个delete

关于其他问题,基于Documentation

MyClass * p1 = new MyClass[5]; // allocates and constructs five objects

【讨论】:

    【解决方案2】:

    只要您重新分配指针而不使用delete[] 来取消分配堆上分配的内存,就会造成内存泄漏。如果你循环你的aFunction(),就会发生这种情况,因为它每次调用它都会重新分配指针。

    至于你的第二个问题,你的析构函数只会delete[]分配给指针的最后一个数组。

    【讨论】:

    • 运行这段代码会发生什么?我不敢在我的电脑上运行它,但我尝试了一个在线的,并在抛出一个 bad_alloc 后停止了
    • @TitoneMaurice:这正是您自己的计算机上会发生的事情。它完全无害。你的程序会崩溃,然后你的操作系统会回收内存。
    • @TitoneMaurice,系统将在几分之一秒内耗尽您的进程的内存......这是一件非常好的事情,您很快就失败了!您不希望软件出现后期故障。
    • @Benjamin Lindley 抱歉,操作系统会回收内存吗?我以为它会泄漏,直到下次系统启动时才会被释放。
    • @TitoneMaurice See this link
    【解决方案3】:

    是的,当您多次调用该函数时存在内存泄漏,而在每次调用后没有显式释放handler.ptrToInts

    void aFunction()
    {
        handler.ptrToInts = new int[20];
    }
    
    //-----somewhere we see the caller
    
    while(!quit)
        {
          aFunction(); 
        }
    

    然而,这是一个检测泄漏的小例子……你应该学会使用Leak detectorsstatic analyzers

    How do you detect/avoid Memory leaks in your (Unmanaged) code?

    【讨论】:

    • 谢谢,这里有人刚刚将我指向 valgrind.org 进行泄漏检测。
    • valgrind 在您的情况下不起作用,因为您的 main() 中有无限循环。
    • @cwschmidt,可以使用静态分析器。 - 检测无限循环。 :-) ...只是补充一下,如果两者都失败,调试器应该通过:-)
    • @WhiZTiM 当然,但建议只是使用 valgrind。 Valgrind 本身不知道无限循环,并且会一直运行到“内存不足”。即使没有静态代码分析器,优秀的程序员也会在此示例中检测到无限循环。
    【解决方案4】:

    当然有内存泄漏。您在

    中分配整数
    void aFunction()
    {
        handler.ptrToInts = new int[20];
    }
    

    不首先释放旧的整数,例如

    void aFunction()
    {
        delete [] handler.ptrToInts;
        handler.ptrToInts = new int[20];
    }
    

    会的。

    调用aFunction() 将导致“无限”内存分配。 而你的析构函数,它只释放最后分配的整数,甚至永远不会被调用。

    为什么您的处理程序不管理自己的内存?

    在对象外部分配内存并在内部释放内存是非常糟糕的做法,反之亦然。

    为什么不这样实现 Handler 类:

    class Handler
    {
    public:
      Handler();
      ~Handler();
      void aMethod();
    private:
      int* ptrToInts;    
    };
    
    Handler::Handler() {
      handler.ptrToInts = new int[20];
    }
    
    Handler::~Handler() {
      delete[] ptrToInts; 
    }
    
    void Handler::aMethod() {
      delete[] ptrToInts; 
      handler.ptrToInts = new int[20];
    }
    
    int main() {
      bool quit = false;
      Handler handler;
    
      while(!quit) {
        handler.aMethod(); 
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多