未及时释放动态分配内存

在C++中,使用动态分配内存时,必须手动释放使用完毕的内存。如果没有及时释放动态分配的内存,就会发生内存泄漏。内存泄漏会导致程序运行过程中消耗的内存不断增加,最终可能导致程序崩溃。

常见的内存泄漏场景包括:

  1. 忘记使用delete释放new操作符动态分配的单个对象内存。
  2. 忘记使用delete []释放new []操作符动态分配的对象数组内存。
  3. 在循环中动态分配内存,并且没有在每次循环迭代结束后释放内存。
  4. 在异常处理中,动态分配了一些内存,但在异常抛出前没有释放。
int* p = new int;
// 没有在使用完成后释放内存

误用delete/delete[]操作符

C++中的delete操作符用于释放使用new操作符动态分配的单个对象内存,而delete[]操作符用于释放使用new[]操作符动态分配的对象数组内存。如果误用了这两个操作符,就可能发生内存泄漏。

常见的误用场景包括:

  1. 使用delete释放使用new[]动态分配的对象数组内存。
  2. 使用delete[]释放使用new动态分配的单个对象内存。
  3. 使用delete释放未被动态分配的内存。
  4. 重复释放同一个内存块。
int* p = new int[10];
// 误用delete释放对象数组内存
delete p;

循环引用导致的内存泄漏

循环引用指的是两个或多个对象之间相互引用,形成一个环状结构。当这些对象不再被使用时,如果没有正确地解除引用,就会导致内存泄漏。

循环引用可能出现在多个对象之间的相互引用、对象与回调函数之间的引用等情况下。这种情况下,因为引用计数不为0,即使没有其他指针指向这些对象,它们也不会被销毁,从而导致内存泄漏。

class A {
public:
  void setB(B* ptr) {
    b = ptr;
  }
private:
  B* b;
};

class B {
public:
  void setA(A* ptr) {
    a = ptr;
  }
private:
  A* a;
};

A* objA = new A();
B* objB = new B();
// 互相引用,无法被销毁
objA->setB(objB);
objB->setA(objA);