• new、delete、动态数组初始化、野指针、解引用、内存池、重载new和delete、内存泄漏等,释放崩溃


    一、野指针

    • 指针变量没有被初始化。任何指针变量刚被创建时不会自动成为nullptr指针,它的缺省值是随机的,所以指针变量在创建的同时应当被初始化,要么将指针设置为nullptr,要么让它指向合法的内存。

    • 指针p被free或者delete之后,没有置为nullptr,让人误以为p是个合法的指针。

    • 指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:

    class A
    {
    public:
    	void Func(void) { std::cout << " test" << std::endl; }
    };
    
    void Test()
    {
    	A* p;
    	{
    		A  a;
    		p = &a; // 注意a的生命期
    	}
    	p->Func();  // p是野指针
    }
    

    二、解引用

    使用*解引用

    解引用再取地址和指针有什么区别???本质上是一样的,可以去实现一下stl容器的迭代器。

    三、动态数组初始化

    四、重载new和delete

    五、内存池

    转载:内存池技术

    转载:内存池设计与实现

    六、内存泄漏

    如何判断是否有内存泄漏

    使用Purify检测内存是否泄漏

    不用工具判断内存是否有泄漏:new和delete是否匹配

    怎么解决内存泄漏

    七、new失败、内存耗尽如何处理

    • 判断指针是否为NULL,如果是则马上用return语句终止本函数

    • 判断指针是否为NULL,如果是则马上用exit(1)终止整个程序的运行。

    • 为new和malloc设置异常处理函数。

    八、free()崩溃

    free或delete异常

    • 释放的指针地址是否和new或malloc出来的一致

    • 释放的指针大小是否被改变

    转载:free()崩溃原因总结

    • 越界、漏写sizeof()、realloc()第二个参数写错

    • 改变指针的指向

    • 重复释放内存

    • 释放不是动态申请的内存

    八、获取new或malloc出来的指针指向的实际内存大小

    _msize()

    九、注意

    • delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉。

    • ❓ 程序崩溃或退出后系统会自动释放内存,为什么在程序退出前还要释放内存?

    示例代码:

    点击查看代码
    #include <iostream>
    #include <string>
    
    int main()
    {
        int* p0 = new int[3]();  //为一个大小为三的数组申请内存空间,p0保存的是首地址,数组所有元素的值为0,内置基本数据类型最好使用()初始化
        int* p1 = new int[3];    //为一个大小为三的数组申请内存空间,p1保存的是首地址,数组所有元素的值未知
        int* p2 = new int(3);    //申请一个内存空间,里面的值为3
        std::string* str1 = new std::string[3];        //调用默认构造函数,str1为空,
        std::string* str2 = new std::string[3]();      //调用默认构造函数,str2为空
        std::string* str3 = new std::string("Hello");  //初始化为Hello
        for (int i = 0; i < 3; i++)
        {
            p1[i] = 3 * i;
        }
        for (int i = 0; i < 3; i++)
        {
            std::cout << *p1 + i << std::endl;      //0,1,2  *p1 值的基础上 +i  先解引用后++
            std::cout << *(p1 + i) << std::endl;  //0,3,6  将地址 +i,再解引用得到下一个地址对应的值
        }
        std::cout << *p2 << std::endl;
    
        delete[] p0;
        delete[] p1;    //基本数据类型,new的时候使用了[],delete也最好使用[],
        delete p2;
    
        delete[] str1;  //类类型(自定义数据类型),new的时候使用了[],delete必须使用[],不然会存在潜在风险
        delete[] str2;
        delete str3;
    
        p0 = nullptr;
        p1 = nullptr;  //如果不指向nullptr,delete之后,p1将是一个随机值,成为一个野指针
        p2 = nullptr;  //我们在删除一个指针之后,编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身
        str1 = nullptr;
        str2 = nullptr;
        str3 = nullptr;
    
        return 0;
    }
    

    转载,还没看完

  • 相关阅读:
    微服务实战系列(七)-网关springcloud gateway
    微服务实战系列(六)-网关springcloud zuul
    微服务实战系列(五)-注册中心Eureka与nacos区别
    微服务实战系列(四)-注册中心springcloud alibaba nacos
    中国唯一入选 Forrester 领导者象限,阿里云 Serverless 全球领先
    面对不可避免的故障,我们造了一个“上帝视角”的控制台
    实习就参与“服务过亿用户的项目”,是什么体验?
    Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题
    云原生时代下,容器安全的“四个挑战”和“两个关键”
    OpenKruise v0.8.0 核心能力解读:管理 Sidecar 容器的利器
  • 原文地址:https://www.cnblogs.com/mmmmmmmmm/p/14020059.html
Copyright © 2020-2023  润新知