在嵌入式系统设计过程中,软件工程师在动态内存管理中会遇到内存丢失的问题,本刊1 月A 期介绍了讨论了跟踪内存丢失面临的困难以及一种将堆栈中的内存碎片降至最少的解决方案,本期将讨论怎样才能找到导致内存丢失的代码段,从而提高(中国)工程师检测内存丢失的能力。 在嵌入式系统设计过程中,要利用数组保存内存分配的每一个块记录,在内存块释放的同时,也将该记录从数组中删除。在主循环的每次迭代之后,分配的内存块的总数目将打印出来。理想情况下,要按类型对这些内存块排序,但指向malloc()和 free()的调用则不包含任何类型信息。内存分配的大小是最好的标识,因此成为设计工程师需要记录的信息。此外,还需要存储分配的内存块地址信息,这样,当调用释放函数时,就可以方便地定位或删除块记录。 在添加和删除块记录时,还需要跟踪每种大小的内存块数目,程序的列表1 给出了实现上述功能的代码。 随着内存块的分配和释放,数组: ======================= typedef struct { void * address; size_t size; } BlockEntry; ====================== 跟踪当前存在的所有内存块。另一数组则跟踪当前存在的每种大小的内存块总数: ====================== typedef struct { int count; size_t size; } Counter; ====================== 函数mDisplayTable()允许我们在每次主循环结束时输出结果。如果printf()不可用,则可利用调试器中断系统并检验数组的内容。 上述代码还必须使NUM_SIZES 和 NUM_BLOCKS 足够大,以处理系统中的大量内存分配;但也不能太大,从而导致在系统运行之前就已耗尽所有的RAM。 输出 快速地浏览代码,可以注意到结构类型Sensor 的长度定义如下: ======================= typedef struct { int offset; int gain; char name[10]; } Sensor; ====================== 假定int 为 32 位数据,那么Sensor 的长度将为18(4+4+10),但在测试中,结果表明为20。编译器可以在存储结构的数据成员之间自由地添加填充,以将对齐强制设定为一个字边界。特殊情况下,每个字段开始于一个已存在的字边界,那么为什么还需要填充呢?填充添加在存储结构的最末端,如果声明了一个数组Sensor, 那么该数组的所有成员(而不仅仅是第一个成员)将会进行字对齐。根据处理器的不同,字对齐的速度将有所差异,有时这些编译器将提供可根据速度选择字对齐长度的切换开关。在任何情形下,最好...