这期内容当中小编将会给大家带来有关如何实现IAR中使用堆和栈的问题分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
堆是什么?
堆是内存空间里为动态内存分配保留的一部分区域
当一个应用需要临时使用一定数量的内存时可以从堆空间分配或借用,C中通过调用malloc()函数实现,C++中通过’new’来实现
当这个内存不再需要时可以通过调用free()函数或者使用delet操作符来释放。一旦该内存被释放,可以再次分配使用。
堆的位置和大小是在编译时静态设置的。
为你的应用分配合适的堆空间很重要,否则在运行时可能崩溃。
怎样决定堆大小
考虑应用使用的动态内存时的首要问题是我需要多少堆空间?
相比来说这更像是估计而不是计算
如果你知道你的应用怎样行动,那么你应该大概知道每个时刻应该分配多少内存
另外需要考虑在管理堆空间是有一些额外的开销
堆管理器需要跟踪已经使用的和剩余的空间数量,已经分配了的块大小,通常还包含一个指向下一个可用内存的指针
另外,开发工具可能为了维护内存体系结构保留一定的内存块。譬如,EWARM编译器通常为保证栈对齐而保留8字节倍数的内存块。
潜在的问题
当不同规模的内存块频繁分配、释放时,动态内存分配是最常发生的问题随之而来。
当内存释放时,就会有一个空位
如果下一个要分配的空间比所有的空位都要大,这就会是个问题
这为debugging带来困难,因为堆上总的空闲内存空间比要分配的要大,但是内存申请可鞥因为空闲空间不连续而失败。
例如,假设如下:
堆的位置为0x20000-0x20FFF
一个8字节的内存块分布在该区间的开始位置
紧接着是一个1024字节的块
之后,第一个块被释放并可以再次使用。然而,应用需要分配大于8字节的空间,所以开始 的8字节空间就无法使用。这就是内存碎片化,如果应用用于不在需要8字节或更少的内存空间,那么这8字节的内存空间就浪费了。这个例子也说明了为什么堆中的小内存块是低效的,这种开销等于应用可用数据的数量。
堆的布局
有些情况下确切的知道堆上有些什么,位于什么位置是非常有用的。
堆上包含的不只是分派的数据:
有一些维护堆的额外开销
每一个分配的内存块都包含两个整数,指针的大小取决于CPU的架构,e.g. ARM器件会使用32bit的整数。
第一个整数指明分派的内存块的大小。
最后一个堆对象后会有一个32bit的值来说明剩余的堆空间。
最后一个堆对象开始位置的32bit值说明这个数据的地址。
堆同时跟踪下一个分配的位置,使用一个驻留在堆外部的结构体中。
typedef struct {
__data_Cell __data * __data *_Plast;
__data_Cell __data *_Head; }
__data_Altab;
指针_Head说明堆的当前状态。指针_Plast说明从哪里开始搜索目前未使用的可用块。
__data_Cell结构体定义如下:
typedef struct __data_Cell
{
__data_size_t _Size;
struct __data_Cell __data *_Next;
} __data_Cell;
其中_Size 说明堆的剩余数量, _Next 说明下一个可用分配的内存地址。如果堆空间耗尽,_Next指针则为NULL。
堆的最终思考
如果没有一些工具辅助你分析动态内存需求,直接估计堆空间是比较困难的。
在桌面Java中有这样的工具(HAT,Heap Analysis Tool)
嵌入式C/C++中还没有类似工具
针对资源有限的嵌入式系统,由于额外的开销和可能的堆内存碎片化,动态内存应该尽量少用。
在你的代码中(测试用例中)你可以创建多个结构体或者对象
MISRA C要求所有内存都必须在编译时静态分配,因此你永远也不会跑出堆空间。
EWARM中的堆统计
EWARM中的C-Spy debugger让你可以看到当前堆的使用情况
要看到这个功能,必须在工程中包含 dlmalloc.c
调用 __iar_dlmallinfo() 和 __iar_dlmalloc_stats() 会在Terminal I/O窗口打印堆统计情况。
4.如果给定太大的栈空间,RAM就浪费了,如果给定的栈空间太小,会出现两种情况(取决于栈在内存空间的位置):
a 变量会被改写,导致未定义的行为
b 栈会超出内存空间,导致应用的异常终止
因为第二种选择比较用于检测到,你应该考虑将栈设置为朝内存重点增长。
静态栈检查器
有很多静态的C语言检查器
Express Logic’s StackX
Abslnt’s StackAnalyzer
John Regher’s Stack Analysis(for AVR/430 only)
AdaCore’s GNATStack
Embedded Workbench’s Stack Plug-in
EW包含一个易用的栈插件,可以监控CSTACK的大小,同时如果你超出指定的栈门限将输出消息到debug日志。
警告:该插件对于RTOS是无效的,使用RTOS时他始终汇报堆栈溢出。
上述就是小编为大家分享的如何实现IAR中使用堆和栈的问题分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。