zoukankan      html  css  js  c++  java
  • 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;
    }
    

    转载,还没看完

  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/mmmmmmmmm/p/14020059.html
Copyright © 2011-2022 走看看