基础知识|C++|内存泄漏与资源管理机制

一、什么是内存泄漏

        内存泄漏(Memory Leak)是指程序中已分配的内存未被及时释放或无法释放,导致这部分内存无法被再次使用的情况。在程序运行过程中,如果持续不断地发生内存泄漏,最终可能导致可用内存耗尽,从而影响程序的性能甚至导致程序崩溃。

二、内存泄流原因和产生的影响

内存泄漏的原因

  • 忘记释放内存

    • 程序员在分配内存之后忘记释放内存。
    • 例如,在 C/C++ 中使用 new 分配内存后忘记使用 delete 或 delete[] 释放内存。
  • 无效指针

    • 指针指向的内存已经被释放,但指针仍然指向该内存区域。
    • 当试图访问该指针时,会导致未定义行为,如程序崩溃。
  • 循环引用

    • 在使用智能指针(如 std::shared_ptr)时,对象之间形成循环引用,导致引用计数永远不会降为零。
    • 这样即使没有指针直接指向这些对象,它们也无法被删除。
  • 资源管理不当

    • 除了内存之外,其他资源(如文件句柄、数据库连接等)也可能发生泄漏。

内存泄漏的影响

  • 性能下降

    • 随着时间的推移,可用内存逐渐减少,导致程序运行变慢。
  • 程序崩溃

    • 当所有可用内存都被占用时,程序可能会因为无法分配更多内存而崩溃。
  • 资源耗尽

    • 在长时间运行的服务中,内存泄漏可能导致整个系统的资源耗尽。

三、C++与Qt,有什么方法解决内存泄露

1.规范代码及时销毁回收资源

2.使用智能指针自动管理资源

3.使用外部内存检测工具检查

4.善用析构函数回收该类使用的资源

5.Qt的父指针管理机制

四、智能指针是什么

        智能指针是一种在现代 C++ 中广泛使用的编程技术,它是一种特殊的指针类型,用于自动管理动态分配的对象的生命周期。智能指针的主要目的是防止内存泄漏和悬挂指针的问题,同时提供更安全和更易于维护的代码。

智能指针的类型

C++ 标准库提供了几种智能指针类型,每种都有其适用场景:

std::unique_ptr:

  • 独占所有权:表示独占拥有一个对象的智能指针。
  • 移动语义:可以通过移动语义转移所有权。
  • 自动删除:当 unique_ptr 走出作用域时,它所拥有的对象会被自动删除。
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "MyClass constructed." << std::endl; }
    ~MyClass() { std::cout << "MyClass destructed." << std::endl; }
};

int main() {
    // 使用 std::unique_ptr
    {
        std::unique_ptr<MyClass> uniqueObj(new MyClass());
        // uniqueObj 管理 MyClass 对象的生命周期
    }  // MyClass 对象在这里被删除

    return 0;
}

std::shared_ptr:

  • 共享所有权:允许多个 shared_ptr 指向同一个对象。
  • 引用计数:内部维护一个引用计数,当最后一个 shared_ptr 对象被销毁或不再指向该对象时,该对象会被删除。
#include <memory>
#include <iostream>

// 角色类
class Character {
public:
    Character(const std::string& name) : name(name) {
        std::cout << "Character created: " << name << std::endl;
    }

    ~Character() {
        std::cout << "Character destroyed: " << name << std::endl;
    }

    void sayHello() const {
        std::cout << "Hello, my name is " << name << "." << std::endl;
    }

private:
    std::string name;
};

int main() {
    // 使用 std::shared_ptr
    {
        // 创建一个角色
        std::shared_ptr<Character> player1 = std::make_shared<Character>("Alice");

        // 角色说你好
        player1->sayHello();

        // 创建第二个角色,并让它指向同一个对象
        std::shared_ptr<Character> player2 = player1;

        // 第二个角色也说你好
        player2->sayHello();

        // 现在 player1 和 player2 都指向同一个 Character 对象
        // 当它们中的任何一个离开作用域时,引用计数会减一
    }  // player1 和 player2 离开作用域,引用计数变为 0,Character 对象被销毁

    return 0;
}

std::weak_ptr:

  • 弱引用:不增加 shared_ptr 的引用计数。
  • 避免循环引用:通常与 shared_ptr 配合使用,解决循环引用问题。
  • #include <memory>
    #include <iostream>
    
    class MyClass {
    public:
        MyClass() { std::cout << "MyClass constructed." << std::endl; }
        ~MyClass() { std::cout << "MyClass destructed." << std::endl; }
    };
    
    int main() {
        // 使用 std::weak_ptr
        {
            std::shared_ptr<MyClass> sharedObj(new MyClass());
            std::weak_ptr<MyClass> weakObj = sharedObj;  // 不增加引用计数
    
            // 检查 weakObj 是否仍然有效
            if (auto strongObj = weakObj.lock()) {
                std::cout << "Still valid." << std::endl;
            } else {
                std::cout << "Invalid." << std::endl;
            }
        }  // MyClass 对象在这里被删除
    
        return 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值