在嵌入式系统设计规划过程中.doc

  1. 1、本文档共6页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
在嵌入式系统设计规划过程中

在嵌入式系统设计过程中,软件工程师在动态内存管理中会遇到内存丢失的问题,本刊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,那么该数组的所有成员(而不仅仅是第一个成员)将会进行字对齐。根据处理器的不同,字对齐的速度将有所差异,有时这些编译器将提供可根据速度选择字对齐长度的切换开关。在任何情形下,最好不要根据源代码的定义对存储结构的长度作任何假设。 2给出了一个显示存储动态内存方式的示例。程序清单2将通常作为主外部循环的迭代了10次,并在每次迭代的末尾,调用函数mDisplay-Table()输出分配的内存块情况。 mClearTable()。 函数replacer():指示了一个用来分配内存块并且直到出现循环迭代才释放的指针。如果检验主循环中的迭代,可以发现分配的内存块并未释放。通过监控总数为20的内存块,从表1可以看出,每次迭代之后的内存块总数都为1,因此没有出现内存丢失。 growAndShrink():管理长度为24个结构体的链表,该链表的长度将随时间发生变化,但我们并不希望链表无限增长。通过检验总数为24的内存块,我们可以发现,虽然任意时间内存块的数目都可能发生变化,但决不会超过25个。 growForever():处理内存块长度为44的情形。这里我们可以非常清晰地看到,分配的内存块数目在持续增长。当首次观察该表时,可能无法找到表的源头。我们首先只能快速而粗略对mMalloc()上的条件断点进行检验,该断点只有当长度参数达到44时才触发。当到达该断点时,可以检验堆栈,以确定进行内存分配的地方。工程师完全能够多次执行这样的操作,因为这种长度的内存块可在多处进行分配。 growForever()中分配的内存不是丢失,因为所有分配的内存块均带有引用,因此理论上可以在后来释放。如果特定应用这样做,那么结果就非常明显。 当不同类型的对象共享相同长度的内存时,上述技术就不那么有效了。实际中碰到这样的情形并不多,但即便可能引发问题,仍然还有很多别的选择。 更为先进的方法则是为每个记录存储类型信息。这并不困难,但我却不愿采用这种方法,因为该方法要求为函数mMalloc()的标记添加一些新东西。我们可以定义一个列出所有可能分配的类型的枚举类型。在每次调用函数mMalloc()时,将传递一个附加的参数,并且该参数为枚举类型中的一个元素。如果在表中该参数连同地址一起被存储,那么总能识别出这类对象。这也使得我们可以将分配长度不同,但类型相关(如可变长度的字符数组)的内存块链接起来。 C++通过使我们重载或删除按类基(per-class basis)而

文档评论(0)

vshoulrengb3 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档