C++内存管理技术内幕

本文探讨了C++内存管理的各个方面,包括内存区域、栈与堆的特性、常用的内存分配函数如new/delete、malloc/free等。还提到了内存分配错误处理、智能指针、内存泄漏检测及解决方案、内存回收以及C++中的内存对象和垃圾回收方法。着重指出new/delete相比于malloc/free的优势在于能够处理对象的构造和析构。
  1. C++内存分配方式
    一个进程被分配的虚拟内存空间包含以下几个区域(从低地址向高地址):文字常量区、代码区、全局区(.data/.bss)、堆区、共享库存储器映射区、栈区、用户栈(存储命令行参数和环境变量)。
    对于这几个区存储的什么内容前面博客有介绍。虚拟内存空间一般是从0x0000 0000-0xffff ffff,大于共4G,前3G是用户空间,后1G是内核空间。
    栈的大小可以设置,在类UNIX平台上,可以在环境变量中设置栈的大小,在Windows平台下,栈的大小在可执行文件当中,一般情况下,不同平台栈空间默认大小如下:

    SunOS/Solaris 8172K bytes (Shared Version),约8M

    Linux 10240K bytes,约10M

    Windows 1024K bytes (Release Version),约1M

    AIX 65536K bytes,是2^16,约128M

    堆大小是可以自己申请的,只要不超过内存都是可以的,最大多少不知道,怎么着都不会超过4G吧。
    malloc/free作用于堆上,new/delete作用于自由存储区。但是由于new是c语言中malloc的简单包装,所以调用系统的new操作符分配的空间其实还是在堆上,所以new操作符分配的对象说它在堆上也合适,说它在自由存储区也合适。但是如果重载new操作符,改用在其他地方分配内存,那么自由存储区的位置就发生了变化,比如可以在全局区。
  2. C++常用内存分配函数
    有new()/delete()、new[]/delete[]、malloc/free,calloc,realloc。
    // 这4个版本可能抛出异常
    void *::operator new(size_t);         // 分配一个对象
    void *::operator new[](size_t);           // 分配一个数组
    void *::operator delete(void*) noexcept;      // 释放一个对象
    void *::operator delete[](void*) noexcept;    // 释放一个数组
    // 这些版本承若不会抛出异常
    void *::operator new(size_t, nothorw_t &);        // 分配一个对象
    void *::operator new[](size_t, nothorw_t &);      // 分配一个数组
    void *::operator delete(void*, nothorw_t &) noexcept; // 释放一个对象
    void *::operator delete[](void*, nothorw_t &) noexcept;   // 释放一个数组
    

    太难了,写不出来,内存管理都是用一本书来介绍的。
    1.不光有系统给的内存分配函数,还可以重载new/delete、new[]/delete[]操作符来实现不同的内存分配策略。
    2.内存分配错误的几种情况以及应对策略。
    3.内存耗尽应对策略
    4.C++智能指针管理内存
    5.内存泄漏定义、内存泄漏发生方式、检测工具以及解决方案
    6.C++内存回收
    7.三种内存对象
    8.C++垃圾回收方法
    下面回答一下常见问题吧

  3. 为什么有了malloc/free还要有new/delete?
    首先必须明确malloc/free是标准库函数,new/delete是运算符。对于非内部对象,无法通过malloc/free来为其动态分配内存,但是new/delete可以,new/delete操作符可以调用构造和析构函数为非内部对象初始化和删除,这些malloc/free都不能做。new/delete能做malloc/free能做的,也能做它不能做的,那是不是可以淘汰malloc/free呢?不可以,因为new函数的实现实际上是对C语言中malloc的简单包装,所以不能淘汰。

    #include <iostream>
    using namespace std;
    
    class Obj{
    public:
        Obj(void){
            cout<<" Construct1"<<endl;
        };
        Obj(int x):data(x){
            cout<<" Construct2"<<endl;
        }
        ~Obj(){
            cout<<" destruct"<<endl;
        }
    private:
        int data;
    };
    
    void Test(void){
        Obj *a=new Obj;
        Obj *b=new Obj(1);
        delete a;
        delete b;
    }
    
    int main(){
        Test();
        return 0;
    }

    输出结果:
     Construct1
     Construct2
     destruct
     destruct

  4. malloc/free、new/delete使用要点
    malloc申请一段内存:

    void * malloc(size_t);
    int *p=(int *)malloc(sizeof(int)*10);
    返回类型为void *,所以需要强制类型转换(int *)
    
    void free(void* membolck);
    free(p);
    被分配的内存重复free会导致程序运行错误,但是对null指针重复释放不会报错。

    new的用法

    new一个对象
    int *p=new int(2);//为一个整型数据分配内存空间
    delete p;
    
    new一个数组
    int *p=new int[len];//申请一段内存空间
    int *p=new int[len]();//初始化为0
    delete[] p;

    new一个自定义对象数组
     

    #include <iostream>
    using namespace std;
    
    class Obj{
    public:
        Obj(void){
            cout<<" Construct1"<<endl;
        };
        Obj(int x):data(x){
            cout<<" Construct2"<<endl;
        }
        ~Obj(){
            cout<<" destruct"<<endl;
        }
        int data;
    };
    
    void Test(void){
        Obj *p=new Obj[10];
        for(int i=0;i<10;++i){
            (p+i)->data=i;
        }
        delete[] p;
    }
    
    int main(){
        Test();
        return 0;
    }

    输出结果:
     Construct1
     Construct1
     Construct1
     Construct1
     Construct1
     Construct1
     Construct1
     Construct1
     Construct1
     Construct1
     destruct
     destruct
     destruct
     destruct
     destruct
     destruct
     destruct
     destruct
     destruct
     destruct

  5. 通过new实现对象的深拷贝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值