zoukankan      html  css  js  c++  java
  • C++Review15_内存管理

    一、野指针

    定义指针变量时最好初始化为NULL;

    内存回收后,指针也用完了,这时候也需要及时将指针置为NULL;

    指针就像野狗一样,为了防止它乱指,除了在使用期间,别的时候都需要置为NULL。这样它就老实了。

    二、栈、堆和静态区

    我们可以简单把内存分为三个部分:静态区、栈、堆

    静态区:保存自动全局变量和static变量(static全局和局部变量)。静态区的内容伴随整个程序的生命周期。在编译时分配;

    栈:保存局部变量,只在函数的范围内存在。当函数运行结束时,这些内容也会自动销毁;特点时效率高,但空间大小有限;

    堆:new/delete分配和释放,在没有释放前一直存在,直到程序结束。特点是使用灵活,空间比较大,但容易出错;

    三、常见内存的错误

    3.1、指针没有指向一个合法的内存

    struct student{

      char* name;

      int score;

    }stu, *pstu;

    结构体里面定义了一个指针;但是指针没有指向一个合法的地址,其内部存的只是一些乱码;

    如果这时候使用strcpy(stu.name,"Jimmy"); 就会出错了,因为会将"Jimmy"往乱码所指的内存上拷贝。这就会导致出错。所以要注意给name指针分配空间后再使用;

    最好就是定义指针->初始化为空指针->再分配空间->检查空间是否分配成功->使用->释放空间->指针置空

    给指针new/malloc空间后,在使用指针之前,为确保指针是有效的。例如:assert(NULL!=p);   assert是一个宏,assert.h

    3.2、为指针分配的内存太小

    char *p1 = "abcdefg";

    char *p2 = (char *)malloc(sizeof(char)*strlen(p1));   //出错,正确应该为 char *p2 = (char*)malloc(strlen(p1)*sizeof(char)+1*sizeof(char));

    strcpy(p2,p1);

    3.3、内存分配成功,但是没有初始化

    int a[10] = {0} 或者 memset函数来初始化:memset(a,0,sizeof(a));

    void *memset(void *str, int ch, size_t n);

    函数解释:将str中前n个字节 (typedef unsigned int size_t )用 ch 替换并返回 str 。memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。

    3.4、内存越界

    操作数组或指针时出现“多1”或“少1”的情况。

    3.5、内存泄漏

    内存new/malloc之后,需要及时delete/free;

    3.6、如何使用malloc函数

    函数原型: (void*)malloc(int size); //参数是int型数据,表示有个

    几个字节大小;函数返回值是void*类型,必须强制转换成你所接收的类型;

    char* p = (char *)malloc(100);

    如果malloc不成功的话,malloc函数会返回NULL,所以要使用if(NULL != p)来验证内存确实分配成功了。

    3.7、用malloc函数申请0字节内存

    用malloc(0)函数申请0字节会返回NULL指针吗?答案是不会,会返回一个正常的内存地址。但是我们却无法使用这块大小为0的内存。

    3.8、内存释放

    内存的申请和释放一定要成对存在。

    不能申请一次,没有释放,这会导致内存泄漏。

    同时不能申请一次,两次释放,因为第二次已经无内存可释放了。

    3.9、内存释放之后

    一定记得要把原先指向该内存的指针置为null;

    C/C++内存模型https://www.cnblogs.com/Stultz-Lee/p/6751522.html

    C分为四个区:堆,栈,静态全局变量区,常量区

    C++内存分为5个区域(堆栈全常代 ):

    1. 堆 heap :
      由new分配的内存块,其释放编译器不去管,由我们程序自己控制(一个new对应一个delete)。如果程序员没有释放掉,在程序结束时OS会自动回收。涉及的问题:“缓冲区溢出”、“内存泄露”

    2. 栈 stack :
      是那些编译器在需要时分配,在不需要时自动清除的存储区。存放局部变量、函数参数。
      存放在栈中的数据只在当前函数及下一层函数中有效,一旦函数返回了,这些数据也就自动释放了。

    3. 全局/静态存储区 (.bss段和.data段) :
      全局和静态变量被分配到同一块内存中。在C语言中,未初始化的放在.bss段中,初始化的放在.data段中;在C++里则不区分了。

    4. 常量存储区 (.rodata段) :
      存放常量,不允许修改(通过非正当手段也可以修改)

    5. 代码区 (.text段) :
      存放代码(如函数),不允许修改(类似常量存储区),但可以执行(不同于常量存储区)

    根据c/c++对象生命周期不同,c/c++的内存模型有三种不同的内存区域,即

    1. 自由存储区,动态区、静态区。
    2. 自由存储区:局部非静态变量的存储区域,即平常所说的栈
    3. 动态区: 用operator new ,malloc分配的内存,即平常所说的堆
    4. 静态区:全局变量 静态变量 字符串常量存在位置

    而代码虽然占内存,但不属于c/c++内存模型的一部分

  • 相关阅读:
    Application.Exit()结束程序,但线程还在的解决方法
    Myeclipse2014 SVN安装方法以及项目上传到svn服务器
    MyEclipse中把JSP默认编码改为UTF-8
    005_MyEclipse编码设置
    laravel5.2学习资源
    wechat-php-sdk
    微信邀请卡的开发
    微信JS-SDK实际分享功能
    每个Linux新手都应该记住的10个基本Linux命令
    Linux下定时备份数据库
  • 原文地址:https://www.cnblogs.com/grooovvve/p/12374947.html
Copyright © 2011-2022 走看看