• C/C++总结笔记——关键字3:malloc/free、new/delete、malloc&new区别、内存泄漏


    C/C++中通过new和malloc实现动态内存分配,new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。那么它俩如何使用,有什么区别了。

    1、malloc/free

    C /C++ 库函数 void malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。如果请求失败,则返回 NULL。一般需和free函数配合使用。
    void
    类型表示未确定类型的指针。C,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针。

    #include 
    #include 
    #include 
     
    int main(){
        char *str;
        
        /* 最初的内存分配 */
        str = (char *) malloc(15);//9223372036854775807
        if(!str)
            printf("内存分配失败!");
        else{
            strcpy(str, "runoob");
            printf("String = %s,  Address = %#X\n", str, str);
            
            /* 重新分配内存 */
            str = (char *) realloc(str, 25);
            strcat(str, ".com");
            printf("String = %s,  Address = %#X\n", str, str);
            
            free(str);
        }
        return(0);
    }
    /*输出
    String = runoob,  Address = 0X9F1460
    String = runoob.com,  Address = 0X9F1460
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    注意:malloc内的参数是需要动态分配的字节数,而不是可以存储的元素个数!

    type *var_name = (type*)malloc(sizeof(type)*num);
    
    • 1

    linux的环境下理论最大分配空间为3G,但内存碎片会影响一次能够分配的最大内存空间,实际能够分配的最大空间不足3G(不知道为什么实际运行结果是远远大于3G)。

    //注意:下面代码会导致内存泄漏,可能会出现电脑卡死不动,请运行前做好必要文件的保存
    #include
    #include	
    int main(){
    	int count = 0;
    	while (malloc(1 << 20)){//一次性分配1M的内存空间
    		count++;
    	}
    	printf("%d\n", count);
    	return 0;
    }
    /*输出<30G(win10 64);影响正常
    30446
    */
    /*输出<3T(linux 64);电脑卡死不动,需要强制关机重启
    2429904
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2、new/delete

    C++将malloc和free封装起来并起了新的名字new和delete,实现了普通数据类型内存的动态分配与清除,同时可以对类的对象创建和清理。new和delete都是运算符,不是库函数,不需要单独添加头文件。格式:
    new
    1、类型指针 指针变量名 = new 类型
    2、类型指针 指针变量名 = new 类型(初始值)
    3、类型指针 指针变量名 = new 类型[元素个数]
    delete
    1、delete 指针变量名
    2、delete[] 指针变量名

    #include 
    using namespace std;
     
    int main (){
       // double* pvalue  = new double(29494.4);   // 申请空间并初始化
       auto pvalue  = new double(29494.44);   // 申请空间并初始化
       cout << "Value of pvalue : " << *pvalue << endl;
       delete pvalue;         // 释放内存
       return 0;
    }
    /*输出
    Value of pvalue : 29495
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    一维数组

    int *array=new int [m];// 动态分配,数组长度为 m
    delete [] array;//释放内存
    
    • 1
    • 2

    二维数组

    int **array
    // 假定数组第一维长度为 m, 第二维长度为 n
    // 动态分配空间
    array = new int *[m];
    for( int i=0; i<m; i++ ){
        array[i] = new int [n]  ;
    }
    //释放
    for( int i=0; i<m; i++ ){
        delete [] array[i];
    }
    delete [] array;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    可以看出动态分配多维数组时,需要为每个元素单独去申请,单独释放。

    new去申请对象会先申请对象的空间并调用对象的构造函数完成对象的初始化;delete会先去完成对象的资源清理,再将对象所占的空间释放掉。

    3、malloc&new区别

    1、C/C++中,malloc和free是标准库函数,支持覆盖;C++中,new和delete是操作符,支持重载
    2、malloc申请的空间不会初始化,new可以初始化
    3、malloc申请空间时需要手动计算空间大小并传递,new不需要;
    4、malloc的返回值为void*,使用时必须强转来接收,new不需要;
    5、malloc申请失败时返回NULL,new申请失败会抛异常
    6、申请自定义类型的对象时,malloc/free不会调用构造函数和析构函数,而new会申请空间后调用构造函数,delete会调用析构函数后再释放空间。

    4、内存泄漏

    内存泄漏是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏并非指内存在物理上消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制。
    一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光,最终的结果就是导致内存溢出。

    造成内存泄露常见的情况:
    1、动态申请单的内存未释放;
    2、指针重新赋值
    3、错误的内存释放
    4、返回值的不正确处理

    解决方法:智能指针。

    https://www.runoob.com/cprogramming/c-function-malloc.html
    https://blog.csdn.net/yaotengjian/article/details/79774002
    https://blog.csdn.net/weixin_44718794/article/details/107071169

  • 相关阅读:
    Python Flask Web教程:make_response的详细用法
    TV焦点实战总结
    【2022年11月22日提高A组】数论计算【SPFA】【数学】
    C#——Property属性详情
    c++11 thread 新线程的启动(一)
    【C语言】二维数组
    vm16安装ubuntuServer22.04并安装docker
    Vue解决Echarts组件使用ID不能复用问题
    变量的介绍
    CentOS7和CentOS8 Asterisk 20.0.0 简单图形化界面3--安装dahdi驱动
  • 原文地址:https://blog.csdn.net/LW_12345/article/details/127665944