你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

C语言基础分享——内存管理2

2021/10/30 12:19:13

内存分配的三种方式:

      静态存储区域分配:内存在编译时就已经分配好,这块内存在整个运行期间都存在,例如全局变量、static修饰的变量等。

      在栈上分配:在执行函数时,函数内的局部变量的内存都在栈上分配,函数执行结束这些内存会自动被释放。栈内存的分配运算使用内置于处理器的指令集,效率高,但分配的内存有限。

      在堆上分配,也称动态分配:程序在运行时用malloc或new申请所需要的内存,程序员自己负责何时用free或delete释放内存。动态内存生存周期由程序员决定,使用灵活,但问题也最多。

野指针:

     听名字就知道,这是一个没人要的指针。他不指向可用内存,也不指向NULL,他是指向不可用内存的指针。野指针是很危险的,因为if语句对他不起作用,他不指向NULL,他指向内存,只是这块内存不可用,所以我们写程序时尽量避免出现野指针。

野指针形成的原因主要如下:

(1)指针没有被初始化。任何指针变量在刚创建时不会自动成为NULL指针,它的默认值是随机的。所以创建指针变量时注意把指针初始化为NULL或者指向合法的内存。例如:

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

(2)当指针p和str被释放之后,没有设置为NULL指针,这时候p和str仍然会指向原来的内存,但是原来的内存已经释放了,不可用了,这时候p和str就成了野指针。这时候即使你用if(p!=NULL)进行防错处理,也没有用,因为p指向的不是NULL,也不是合法内存。

常见的内存错误及对策:

      我们在写程序的时候,最常见的内存错误就是段错误,这种错误在编译时编译器并不能发现,只有运行时才会被发现。所以分享一下目前了解到的几个内存错误和解决策略。

(1)内存分配不成功,但使用了它。我们申请内存,不是每一次都会成功,也可能会有分配不成功的时候。如果指针p是函数的参数,在函数入口处用assert(p!=NULL)进行检查;如果是用malloc或new申请内存,就用if(p==NULL)或者if(p!=NULL)检查,进行防错处理。

(2)内存分配成功,但未初始化就使用了它。分配了内存,一定要记得初始化,哪怕初始化为0.

(3)忘记释放内存,造成内存泄漏。对于这种错误,最开始并不会发现问题,当系统运行久了的时候,你会发现程序突然死掉了,原因就是拥有malloc申请的函数被调用多次之后,堆内存已经找不到内存分配了。所以动态分配一定要记得malloc和free,new和delete成对使用。

(4)对内存的操作超过了边界

例如如下代码:​​​​​​​

char *p=(char)malloc(4);*(p+5)=5;

       在这段代码中,p指向的是申请出来的空间里的第一块内存,我们只申请的四块,所以指向第五块的时候就会出现段错误,第五块内存是不可用的,我们不能往里面赋值。在正常使用中,这种问题一般出现在for循环中,循环次数容易搞错。

(5)释放了内存却继续使用它。如果是因为调用关系复杂,思路混乱,这时应该重新设计数据结构,最好在写代码先画个模型图,把调用关系弄清楚。还可能出现在函数中,return返回指针,不能是指向局部变量的指针,因为函数运行结束局部变量的内存就被回收了,还有就是出现了野指针。

下次介绍一些段错误以及调试方法,其实这里已经提到了,只要是访问了不该访问的内存段都叫段错误。比如,野指针指向的那块内存,只要访问就是段错误,访问越界也是段错误。