MST

星途 面试题库

面试题:C++ 动态内存管理中内存泄漏场景及智能指针解决方法

列举至少三种在 C++ 动态内存管理中可能导致内存泄漏的场景,并说明如何使用智能指针来避免这些内存泄漏情况。同时,解释在这些场景下智能指针的工作原理。
31.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

可能导致内存泄漏的场景

  1. 忘记释放内存:在使用new分配内存后,没有对应的delete语句。例如:
void memoryLeak1() {
    int* ptr = new int;
    // 这里没有delete ptr,导致内存泄漏
}
  1. 异常抛出时未释放内存:在分配内存后,执行过程中抛出异常,导致后续的delete语句未执行。
void memoryLeak2() {
    int* ptr = new int;
    // 假设这里抛出异常
    throw std::exception();
    delete ptr; // 由于异常,这行代码不会执行,内存泄漏
}
  1. 动态分配数组未正确释放:使用new[]分配数组内存,却用delete而非delete[]释放。
void memoryLeak3() {
    int* arr = new int[10];
    delete arr; // 应该用delete[] arr,否则会内存泄漏
}

使用智能指针避免内存泄漏及原理

  1. std::unique_ptr
    • 避免内存泄漏方式
void avoidLeak1() {
    std::unique_ptr<int> ptr(new int);
    // 作用域结束时,std::unique_ptr自动调用delete释放内存
}
- **工作原理**:`std::unique_ptr`采用独占所有权模式,它拥有指向对象的唯一指针。当`std::unique_ptr`对象销毁(例如离开作用域)时,其析构函数会自动调用`delete`释放所指向的内存,从而确保不会发生忘记释放内存的情况。对于数组,有`std::unique_ptr<int[]>`,其析构函数会调用`delete[]`。

2. std::shared_ptr: - 避免内存泄漏方式

void avoidLeak2() {
    std::shared_ptr<int> ptr(new int);
    // 多个std::shared_ptr可指向同一对象,当最后一个指向对象的std::shared_ptr销毁时,内存被释放
}
- **工作原理**:`std::shared_ptr`采用引用计数的方式管理内存。多个`std::shared_ptr`可以指向同一个对象,每个`std::shared_ptr`内部维护一个引用计数。当一个`std::shared_ptr`对象创建时,引用计数加1;当一个`std::shared_ptr`对象销毁时,引用计数减1。当引用计数降为0时,表示没有任何`std::shared_ptr`指向该对象,此时自动调用`delete`释放内存,从而避免了异常抛出等情况下内存未释放的问题。

3. std::weak_ptr(配合std::shared_ptr: - 避免内存泄漏方式:主要用于解决std::shared_ptr的循环引用问题。例如:

class B;
class A {
public:
    std::shared_ptr<B> ptrB;
};
class B {
public:
    std::weak_ptr<A> ptrA; // 使用std::weak_ptr避免循环引用
};
- **工作原理**:`std::weak_ptr`不增加引用计数,它是对`std::shared_ptr`所管理对象的一种弱引用。当`std::shared_ptr`的引用计数为0并释放对象后,`std::weak_ptr`可以检测到所指向的对象已被释放,避免了因循环引用导致的内存泄漏。通过`lock()`方法,`std::weak_ptr`可以尝试获取一个`std::shared_ptr`,如果对象已被释放,`lock()`将返回一个空的`std::shared_ptr`。