Flag Counter

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++内存模型的一部分

posted @ 2020-02-27 22:27  Grooovvve  阅读(...)  评论(...编辑  收藏
Flag Counter