Error[8]: Undefined offset: 31, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

1.C++内存机制 1.栈(Stack),函数中的局部变量,由编译器负责分配释放,函数结束,变量释放。 2.堆(Heap),通过new 申请的内存,由delete或delete[]释放 3.自由存储区(Free Storage),由程序员用malloc,calloc/realloc分配,free进行释放,忘记free,会导致内存泄漏,程序结束时,该区域内存由OS回收 4.全局区/静态区(Global Static Area),全局变量和静态变量存储区。程序编译完成后,该区域便存在,在C++中,由于全局变量和静态变量编译器会给这些变量自动初始化赋值,所以没区分初始化变量和未初始化变量。由于全局变量一直占据内存空间且不易维护,推荐少用,程序结束时释放。 5.常量存储区,比较特殊,专门存储不能修改的变量。 注意事项

【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL,防止使用指针值为NULL的内存,可以在函数入口处断言检测。

【规则2】不要忘记为数组或动态内存赋初值(比如calloc比malloc就要好),指针初始化为NULL(c++中为0)。

【规则3】避免数组或指针下标越界,特别

当心发生“多1”或者"少1"的 *** 作。

【规则4】动态内存的申请和释放必须配对,防止内存泄露,具体为malloc/calloc/realloc和free配对,new和delete以及delete[]配对。

【规则5】用free或者delete释放内存后,应立即将指针设置为NULL(C++中为0),防止产生“野指针”、"悬垂指针"。

【规则6】遇到不懂得问题及时debug,一般的虫子

debug一下就灰飞烟灭了,一切bug都是浮云而已

内存管理分为 一.内存管理机制 二.内存泄漏机制 三.内存回收机制

内存溢出:程序在申请内存时,没有足够的内存空间供其使用 内存泄漏:程序在申请内存后,无法释放已申请的内存空间,占用有用内存,最终导致内存溢出 内

/******************************************************

内存空间的布局

◼ 每个应用都有自己独立的内存空间,其内存空间一般都有以下几大区域

✓ 用于存放代码

✓ 用于存放全局变量等

✓ 每调用一个函数就会给它分配一段连续的栈空间,等函数调用完毕后会自动回收这段栈空间

✓ 自动分配和回收

✓ 需要主动去申请和释放

堆空间

◼ 在程序运行过程,为了能够自由控制内存的生命周期、大小,会经常使用堆空间的内存

◼ 堆空间的申请\释放

char *p = (char *) malloc(4);
p[0] = 10;
p[1] = 11;
p[2] = 12;
p[3] = 13;
free(p);

int *p = (int *) malloc(4);
*p = 10;
free(p);

 

X86环境(32bit)

int *p = new int;
*p = 10
delete p;

char *p = new char;
*p = 10;

delete p;

char *p = new char[4];

delete[] p;

◼ 注意

◼ 现在的很多高级编程语言不需要开发人员去管理内存(比如Java),屏蔽了很多内存细节,利弊同时存在

堆空间的初始化

memset

◼ memset函数是将较大的数据结构(比如对象、数组等)内存清零的比较快的方法

int size = sizeof(int) * 10;
int *p = (int *) malloc(size);
// memory set
memset(p, 0, size);

int *p0 = new int;
int *p1 = new int();
int *p2 = new int(5);

cout << *p0 << endl;
cout << *p1 << endl;
cout << *p2 << endl;

0 (mac)下为0
0
5

对象的内存

◼ 对象的内存可以存在于3种地方

构造函数(Constructor)

◼ 构造函数(也叫构造器),在对象创建的时候自动调用,一般用于完成对象的初始化工作

struct Person {
   int m_age;

   Person() {
      m_age = 0;
      cout << "Person()" << endl;
   }

   Person(int age) {
      m_age = age;
      cout << "Person(int age)" << endl;
   }
};

◼ 特点

◼ 注意

struct Person {
   int m_age;

   Person() {
      m_age = 0;
      cout << "Person()" << endl;
   }
};
int main() {c
    Person person0; // Person()
}
//输出 : Person()

看汇编码的话 LLDB 里用 disas 命令

disas

struct Person {
    int m_age;
};
int main() {

    Person person0; // Person()
    person0.m_age = 10;
    
}

当没有默认的构造函数的时候,可以供汇编代码可以看到,整个汇编代码执行,只有一句 *** 作movl struct Person { int m_age=8; }; xa, -0x8(%rbp),没有任何call函数调用的初始化 *** 作。

  • 函数名以~开头,与类同名,无返回值(void都不能写),无参,不可以重载,有且只有一个析构函数
  • ==在某些特定的情况下,编译器才会为类生成空的无参的构造函数==

    成员变量的初始化

    struct Person {
       int m_age;
    
    };
    
    // 全局区:成员变量初始化为0
    Person g_person;
    
    void test() {
       // 栈空间:没有初始化成员变量
       // Person person; 
    
       // 堆空间:没有初始化成员变量
       Person *p0 = new Person;
       // 堆空间:成员变量初始化为0
       Person *p1 = new Person();
    
       cout << g_person.m_age << endl;
       // cout << person.m_age << endl;
       cout << p0->m_age << endl;
       cout << p1->m_age << endl;
    }
    
    析构函数(Destructor)

    ◼ 析构函数(也叫析构器),在对象销毁的时候自动调用,一般用于完成对象的清理工作

    ◼ 特点

    ◼ 注意

    ◼ 构造函数、析构函数要声明为public,才能被外界正常使用

    using namespace std;
    
    struct Car {
       int m_price;
    
       Car() {
          m_price = 0;
          cout << "Car::Car()" << endl;
       }
    
       ~Car() {
          cout << "Car::~Car()" << endl;
       }
    };
    
    struct Person {
    private:
       int m_age;
       Car *m_car;
    public:
       // 用来做初始化的工作
       Person() {
          m_age = 0;
          m_car = new Car();
           
          cout << "Person::Person()" << endl;
       }
    
       // 用来做内存清理的工作
       ~Person() {
          delete m_car;
          cout << "Person::~Person()" << endl;
       }
    };
    

    int main() {
       {
          Person person;
       }
    
       int age = 20;
       int *p = &age;
    
       return 0;
    }
    

    [+++]

    Car::Car()
    Person::Person()
    Car::~Car()
    Person::~Person()



     

    )
    File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
    File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
    File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
    C++内存空间管理_C_内存溢出

    C++内存空间管理

    C++内存空间管理,第1张

    1.C++内存机制 1.栈(Stack),函数中的局部变量,由编译器负责分配释放,函数结束,变量释放。 2.堆(Heap),通过new 申请的内存,由delete或delete[]释放 3.自由存储区(Free Storage),由程序员用malloc,calloc/realloc分配,free进行释放,忘记free,会导致内存泄漏,程序结束时,该区域内存由OS回收 4.全局区/静态区(Global Static Area),全局变量和静态变量存储区。程序编译完成后,该区域便存在,在C++中,由于全局变量和静态变量编译器会给这些变量自动初始化赋值,所以没区分初始化变量和未初始化变量。由于全局变量一直占据内存空间且不易维护,推荐少用,程序结束时释放。 5.常量存储区,比较特殊,专门存储不能修改的变量。 注意事项

    【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL,防止使用指针值为NULL的内存,可以在函数入口处断言检测。

    【规则2】不要忘记为数组或动态内存赋初值(比如calloc比malloc就要好),指针初始化为NULL(c++中为0)。

    【规则3】避免数组或指针下标越界,特别

    当心发生“多1”或者"少1"的 *** 作。

    【规则4】动态内存的申请和释放必须配对,防止内存泄露,具体为malloc/calloc/realloc和free配对,new和delete以及delete[]配对。

    【规则5】用free或者delete释放内存后,应立即将指针设置为NULL(C++中为0),防止产生“野指针”、"悬垂指针"。

    【规则6】遇到不懂得问题及时debug,一般的虫子

    debug一下就灰飞烟灭了,一切bug都是浮云而已

    内存管理分为 一.内存管理机制 二.内存泄漏机制 三.内存回收机制

    内存溢出:程序在申请内存时,没有足够的内存空间供其使用 内存泄漏:程序在申请内存后,无法释放已申请的内存空间,占用有用内存,最终导致内存溢出 内

    /******************************************************

    内存空间的布局

    ◼ 每个应用都有自己独立的内存空间,其内存空间一般都有以下几大区域

    • 代码段(代码区)

    ✓ 用于存放代码

    • 数据段(全局区)

    ✓ 用于存放全局变量等

    • 栈空间

    ✓ 每调用一个函数就会给它分配一段连续的栈空间,等函数调用完毕后会自动回收这段栈空间

    ✓ 自动分配和回收

    • 堆空间

    ✓ 需要主动去申请和释放

    堆空间

    ◼ 在程序运行过程,为了能够自由控制内存的生命周期、大小,会经常使用堆空间的内存

    ◼ 堆空间的申请\释放

    • malloc \ free
    • new \ delete
    • new [] \ delete []

    char *p = (char *) malloc(4);
    p[0] = 10;
    p[1] = 11;
    p[2] = 12;
    p[3] = 13;
    free(p);
    

    int *p = (int *) malloc(4);
    *p = 10;
    free(p);
    

     

    X86环境(32bit)

    int *p = new int;
    *p = 10
    delete p;
    

    char *p = new char;
    *p = 10;
    
    delete p;
    

    char *p = new char[4];
    
    delete[] p;
    

    ◼ 注意

    • 申请堆空间成功后,会返回那一段内存空间的地址
    • 申请和释放必须是1对1的关系,不然可能会存在内存泄露

    ◼ 现在的很多高级编程语言不需要开发人员去管理内存(比如Java),屏蔽了很多内存细节,利弊同时存在

    • 利:提高开发效率,避免内存使用不当或泄露
    • 弊:不利于开发人员了解本质,永远停留在API调用和表层语法糖,对性能优化无从下手

    堆空间的初始化

    memset

    ◼ memset函数是将较大的数据结构(比如对象、数组等)内存清零的比较快的方法

    int size = sizeof(int) * 10;
    int *p = (int *) malloc(size);
    // memory set
    memset(p, 0, size);
    

    int *p0 = new int;
    int *p1 = new int();
    int *p2 = new int(5);
    
    cout << *p0 << endl;
    cout << *p1 << endl;
    cout << *p2 << endl;
    

    0 (mac)下为0
    0
    5

    对象的内存

    ◼ 对象的内存可以存在于3种地方

    • 全局区(数据段):全局变量

    • 栈空间:函数里面的局部变量

    • 堆空间:动态申请内存(malloc、new等)

    构造函数(Constructor)

    ◼ 构造函数(也叫构造器),在对象创建的时候自动调用,一般用于完成对象的初始化工作

    struct Person {
       int m_age;
    
       Person() {
          m_age = 0;
          cout << "Person()" << endl;
       }
    
       Person(int age) {
          m_age = age;
          cout << "Person(int age)" << endl;
       }
    };
    

    ◼ 特点

    • 函数名与类同名,无返回值(void都不能写),可以有参数,可以重载,可以有多个构造函数

    • 一旦自定义了构造函数,必须用其中一个自定义的构造函数来初始化对象

    ◼ 注意

    • 通过==malloc分配的对象不会调用构造函数==

    struct Person {
       int m_age;
    
       Person() {
          m_age = 0;
          cout << "Person()" << endl;
       }
    };
    int main() {c
        Person person0; // Person()
    }
    //输出 : Person()
    

    看汇编码的话 LLDB 里用 disas 命令

    disas
    

    struct Person {
        int m_age;
    };
    int main() {
    
        Person person0; // Person()
        person0.m_age = 10;
        
    }
    

    当没有默认的构造函数的时候,可以供汇编代码可以看到,整个汇编代码执行,只有一句 *** 作movl struct Person { int m_age=8; }; xa, -0x8(%rbp),没有任何call函数调用的初始化 *** 作。

  • 函数名以~开头,与类同名,无返回值(void都不能写),无参,不可以重载,有且只有一个析构函数
  • ==在某些特定的情况下,编译器才会为类生成空的无参的构造函数==

    成员变量的初始化

    struct Person {
       int m_age;
    
    };
    
    // 全局区:成员变量初始化为0
    Person g_person;
    
    void test() {
       // 栈空间:没有初始化成员变量
       // Person person; 
    
       // 堆空间:没有初始化成员变量
       Person *p0 = new Person;
       // 堆空间:成员变量初始化为0
       Person *p1 = new Person();
    
       cout << g_person.m_age << endl;
       // cout << person.m_age << endl;
       cout << p0->m_age << endl;
       cout << p1->m_age << endl;
    }
    
    析构函数(Destructor)

    ◼ 析构函数(也叫析构器),在对象销毁的时候自动调用,一般用于完成对象的清理工作

    ◼ 特点

    • 通过malloc分配的对象free的时候不会调用析构函数

    ◼ 注意

      class Person { int m_age; public: // 新的Person对象诞生的象征 Person() { cout << "Person::Person()" << endl; } // 一个Person对象销毁的象征 ~Person() { cout << "~Person()" << endl; } };

    ◼ 构造函数、析构函数要声明为public,才能被外界正常使用

    using namespace std;
    
    struct Car {
       int m_price;
    
       Car() {
          m_price = 0;
          cout << "Car::Car()" << endl;
       }
    
       ~Car() {
          cout << "Car::~Car()" << endl;
       }
    };
    
    struct Person {
    private:
       int m_age;
       Car *m_car;
    public:
       // 用来做初始化的工作
       Person() {
          m_age = 0;
          m_car = new Car();
           
          cout << "Person::Person()" << endl;
       }
    
       // 用来做内存清理的工作
       ~Person() {
          delete m_car;
          cout << "Person::~Person()" << endl;
       }
    };
    

    int main() {
       {
          Person person;
       }
    
       int age = 20;
       int *p = &age;
    
       return 0;
    }
    

     
    

    Car::Car()
    Person::Person()
    Car::~Car()
    Person::~Person()



     

    欢迎分享,转载请注明来源:内存溢出

    原文地址: http://outofmemory.cn/langs/792821.html

    (0)
    打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
    上一篇 2022-05-05
    下一篇 2022-05-05

    发表评论

    登录后才能评论

    评论列表(0条)

    保存