020-88888888
18680929068
很多工程师都告诉,C/C++语言与其他语言有所不同,它必须开发者自己管理内存资源,动态内存使用不当,更容易导致段错误或者内存外泄,因此内存管理至关重要。本文将以C语言为事例讲解动态内存管理的原理。
C/C++语言与其他语言有所不同,它必须开发者自己管理内存资源。对于动态内存的使用不当更容易导致段错误或者内存外泄。特别是在是内存外泄,内存外泄往往是在程序运行一段时间才不会被找到,使得开发人员无法第一时间定位错误。而比起于个人计算机,嵌入式系统的内存资源堪称匮乏。
作为嵌入式C的开发人员,理解其内存管理的原理能使其更为正确地用于内存资源以及定位程序的bug。本文将以C语言为事例讲解动态内存管理的原理。
动态内存的原理1、栈空间与填空间在讲解内存管理之前,我们再行解释一下栈空间与填空间:栈空间是由编译器自动分配获释,对于AWorks等操作系统,在用户创立一个任务的时候可以由自己要求任务栈空间的大小。栈空间里面一般存放在着如下数据:在函数内的局部变量(不还包括static定义的变量),在调用另一个函数时留存的通用寄存器信息等。参照如下例程(为了便于解读,省略通用寄存器等信息):在task继续执行s=calculate_sum(a,b);之前,task的栈内留存如下数据:程序接下来继续执行calculate_sum函数,其栈向上快速增长。
在回到task之前,其栈结构如下:继续执行完了calculate_sum之后,根据回到地址回到task之后,栈完全恢复调用之前的结构:所以栈空间存储着代码块内的局部变量,动态地变动着内部的数据。这也就是为什么当模块调用完结后变量就仍然“存活”的原因。
填空间是由OS管理的一片区域,开发者须向OS动态申请人一片区域用作操作者数据。填空间在程序运行时仍然有效地,相等于定义了一个大型的全局数组。必须时向填空间申请人内存,用于完再行还回来。
这样可以使得开发者需要动态地掌控空间的大小,而不必须在写出代码的时候就考虑到最糟的情况(定义一个数组必需在编译器之前就确认其大小,用于过程中无法减少或增加,所以必需考虑到最多必须的数据大小)。填空间由编译器要求,如果开发者想要尝试构建一片动态内存,须向填申请人一片偏移的内存空间。2、内存资源的申请人与获释我们这里以常用的内存操作者模块——malloc与free为事例,讲解操作者动态内存的细节。
void*malloc(size)——申请人一片大小为size字节的内存。参照右图,灰色部分是早已被用于的内存,空白部分则是可以被申请人用于的内存。
在申请人内存的时候,系统不会首先辨别是不是充足大的并未被用于的区域,如果有,则将其分配给申请者,再行将此区域标记为“已用于”;否则分配告终。(为便利读图,从这里开始我们假设内存的地址从上往下快速增长)voidfree(void*)——获释已申请人的内存。与malloc忽略,free的起到是把“已用于”的区域标记为“并未用于”,那么获释的内存下一次就可以再行分配过来适配。
free获释的内存必需是malloc申请人的内存。由于必须对内存展开状态标记和方位记录(以便获释)。在申请人/获释内存的时候必须额外的空间展开信息的记录。有的系统不会将记录的信息集中管理,有的则是申请人内存的时候额外地多申请人一小片区域用作记录。
3、内存外泄对于动态申请人的内存,用于完之后应当送给填,才能在先前之后分配过来。而如果申请人的内存如果没还回来,就造成了内存外泄。
参照如下一段代码:现在我们设flag=1,继续执行这个函数不会再次发生什么?。
本文来源:kaiyun·开云,kaiyun·开云(官方)app下载安装ios/安卓通用版/手机版-www.mingxiasm.com