zoukankan      html  css  js  c++  java
  • C与C艹的内存管理方式

      C 内存开辟出的空间一般可以分成:代码段,数据段(初始化的数据段, 为初始化的数据段BSS),堆,栈

      代码段:保存程序文本,指令指针EIP就是指向代码段,可读可执行不可写
      数据段:保存初始化的全局变量和静态变量,可读可写不可执行
      BSS:未初始化的全局变量和静态变量
      堆(Heap):动态分配内存,向地址增大的方向增长,可读可写可执行  
      栈(Stack):存放局部变量,函数参数,当前状态,函数调用信息等,向地址减小的方向增长,非常非常重要,可读可写可执行
      
      最特别的是 栈stack ,它和别人是反着的!在Windows平台上,栈都是从上(高)向下(低)生长的!。
      关于函数调用举个例子:
    int i= 0x22222222;
    char szTest [] = "aaaa";//a的ASCII码为0x61
    func(i, szTest);

      当访问进入func函数时,栈中的形式为(左侧地址  右侧数据):

      0x0013FCF0   0x0013FCF8

      0x0013FCF4   0x22222222

      0x0013FCF8   0x61616161

    PS: c++中语句解析顺序和函数调用时候顺序一致:由右向左!

    比如如下语句,在输入vector为空时会造成 访问越界!

    void numIslands(vector<vector<char>>& grid) {
            const int n = grid.size(), m = grid[0].size();      
    }

       这里与if语句中的条件判断语句解析顺序相反(从左至右解析if语句).

      c++内存开辟区域分为: 堆 栈 自由存储区 全局/静态存储区 常量存储区

      自由存储区: 由malloc等分配的内存块,他和堆(new)类似,只不过用free结束自己的生命周期.  (其实,可以看做是堆的剩余空间.)

      : 由new分配的内存块,程序员手动控制生成和释放(delete).如果程序员没有是放掉,操作系统自动收回.

      栈: 在执行函数时,函数内部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存内置于处理器的指令集中,效率很高,但是分配的内存容量有限 .

      全局/静态存储区: 全局和静态变量被存储在这个区域. C中将这个区域分为 初始化的 和 为初始化的数据段.C++中二者公用这个区域

      常量存储区: 存放 const常量 不允许修改.

    ****************************以上是基础准备****************************

      malloc与new的区别:

         c++中出现了new与delete这种动态分配内存的方法.

      (1)malloc在自由存储区 而new在堆区.

      (2)malloc与free是C++/C语言的标准库函数new/delete是C++的运算符

        所以标准库函数与运算符可以做的事情是不一样的.  

        malloc与free是不在编译器控制权限之内,不能把构造函数和析构函数的任务强加于malloc/free.

          Here,在biubiu的时候写cocos2d-x,前端就是c++的语法.在一个场景结束的时候总是崩溃,最后问题定位到析构函数.发现类在结束的时候并没有调用析构函数.导致类中使用的一些内存区域没有被释放掉(本来是要留到析构函数里面运行释放内存指针置空的)最后发现是在累的创建时没有使用new而是使用的malloc,然后手动初始化函数,但是析构时并没有手写销毁函数,而是直接将操作写到了析构函数中,但并没有被执行.

        对于非内部数据类型,光用malloc/free无法满足动态对象的要求.因此,C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

    #include <iostream>
    using namespace std;
    
    class Obj
    {
    public:
    
         Obj(void) { cout <<"Initialization"<<endl;}
    
         ~Obj(void) { cout<<"Destory"<<endl;}
    
         void initialization(){ cout<<"Initialization"<<endl;}
    
         void destory(){ cout<<"Destory"<<endl;}
    };
    
    void useMallocFree(void)
    {
         Obj *a = (Obj* ) malloc(sizeof(Obj));
         //a->initialization();
         //a->destory();
         free(a);
    }
    
    void useNewDelete(void)
    {
         Obj *a = new Obj();
         delete a;
    }
    int main()
    {
         useMallocFree();
         useNewDelete();
         return 0;
    }

      因为内部类型没有构造和析构函数,所以二者使等效的.既然new/delete可以覆盖malloc/free的功能为啥还要在C艹中保留malloc/free呢?为了在C艹中调用c程序,毕竟c只支持malloc.

      如果 free new出来的空间,那么可能会因为没执行析构函数而出错;如果delete malloc出来的空间看似没问题,但是可读性很差.所以,建议 配对使用!.!

      

      对于堆和栈:

      (1)频繁的new/delete操作 势必会造成内存碎片化;而栈空间不存在内存碎片化问题.

      (2)成功在函数中开辟内存的方法: a.主函数中给开辟函数传递 指针的地址,在函数中使用二级指针;

                      b.开辟函数返回开辟成功的内存首地址给主函数指针.

      关于如何防止内存空间(堆)碎片化:

      (1)对每一个类重载 new 和 delete. ;目的是从不同固定大小的内存池中分配不同的对象.全局重载或者单个类重载. 使用 malloc外面封装成new 参数是字节数. free 外面封装 delete

      出现问题的情况:

      (1)内存泄露:手动开辟内存空间后,如果没有释放该空间,而且指向该空间的指针指向了别的内存区域,那么造成该空间无法释放.

      (2)野指针:释放内存后要把指向它的指针置为NULL,否则 if != NULL 语句就不能判断出是否是空内存.

      指针与数组:

         完全不一样! 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变.

        指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。

        注意:

    char *GetString(void){
    char p[] = "hello world";
    return p; // 编译器将提出警告
    }
     
    void Test4(void){
    char *str = NULL;
    str = GetString(); // str 的内容是垃圾
    cout<< str << endl;
    }

        与

    char *GetString2(void){
    char *p = "hello world";
    return p;
    }
     
    void Test5(void){
    char *str = NULL;
    str = GetString2();
    cout<< str << endl;
    }

        的区别,前者输出错误,后者输出正确.字符数组开辟在栈上,函数结束自动释放. 字符常量开辟在全局静态存储区.是只读的内存快.

  • 相关阅读:
    Android JNI与多线程
    V8 API Reference Guide
    V8引擎嵌入指南
    google v8引擎常见问题
    Android单例模式
    setTimeout和setInterval
    Android ANR
    android全屏
    Android进程和线程(Android开发指南--译)
    ubuntu下一次网络流量危机
  • 原文地址:https://www.cnblogs.com/luntai/p/5886992.html
Copyright © 2011-2022 走看看