《Design by Contract for Embedded Software》 翻译( 二 )


我们以动态内存分配作为一个例子 。在任何类型的系统中,用 malloc()(或 C++的 new 操作符)分配内存都可能失败 。在通用计算机中,一个失败的 malloc() 仅仅表明,在这一时刻,操作系统不能提供所要求的内存 。在一个高度动态的通用计算环境中,这种情况很容易发生 。当它发生时,你可以选择从这种情况下恢复 。一个选择可能是让应用程序释放它所分配的一些内存,然后重新尝试分配 。另一个选择可能是提示用户问题的存在,并鼓励他们退出其他应用程序,以便当前的应用程序可以收集更多的内存 。然而,另一个选择是将数据保存到磁盘并退出 。不管是什么选择,处理这种情况需要一些激烈的行动,这显然是不符合你的应用程序的主流行为 。然而,你应该设计并实现这样的动作,因为在桌面环境中,malloc () 失败必须被视为一种异常 。
In a typical embedded system, on the other hand, the same failed malloc() probably should be flagged as a bug. That’s because embedded systems offer much fewer excuses to run out of memory, so when it happens, it’s typically an indication of a flaw. You cannot really recover from it. Exiting other applications is not an option. Neither is saving data to a disk and exit. Whichever way you look at it, it’s a bug no different really from overflowing the stack, dereferencing a NULL pointer, or overrunning an array index. Instead of bending over backwards in attempts to handle this condition in software (as you would on the desktop), you should concentrate first on finding the root cause and then fixing the problem. (I would first look for a memory leak, wouldn’t you?)
另一方面,在一个典型的嵌入式系统中,同样失败的 malloc() 可能应该被标记为一个错误 。这是因为嵌入式系统提供的内存耗尽的借口要少得多,所以当它发生时,它通常是一个缺陷的迹象 。你无法真正从中恢复 。退出其他应用程序不是一种选择 。将数据保存到磁盘并退出也不是一种选择 。无论你从哪方面看,这都是一个错误,与堆栈溢出、解读 NULL 指针或超限数组索引没有什么区别 。与其在软件中弯腰试图处理这种情况(就像在桌面上一样),你应该首先集中精力找到根本原因,然后解决问题 。(如我首先会寻找内存泄漏,你会吗?)
The main point here is that many situations traditionally handled as exceptional conditions in general-purpose computing are in fact bugs in embedded systems. In other words, the specifics of embedded systems (computers dedicated to a single, well-defined purpose) allow you to considerably simplify the embedded software by flagging many situations as bugs (that you don’t need to handle) rather than exceptional conditions (that you do need to handle). The correct distinction between these two situations always depends on the context, so you should not blindly transfer the rules of thumb from other areas of programming to embedded real-time systems. Instead, I propose that you critically ask yourself the following two probing questions: “Can a given situation legitimately arise in this particular system?” and “If it happens, is there anything specific that needs to or can be done in the software?” If the answer to either of these questions is “yes,” then you should handle the situation as an exceptional condition; otherwise, you should treat the situation as a bug.
这里的主要观点是,许多在传统的通用计算中作为异常 (特殊情况) 处理的情况,在嵌入式系统中实际上表现为错误 。换句话说,嵌入式系统(专门用于单一的、定义明确的用途的计算机)的特性允许你通过将许多情况标记为 bug(你不需要处理)而不是异常(你需要处理)来大大简化嵌入式软件 。这两种情况的正确区分总是取决于上下文,所以你不应该盲目地将其他编程领域的经验法则转移到嵌入式实时系统中 。相反,我建议你批判性地问自己以下两个探究性问题 。"在这个特定的系统中,一个特定的情况会合法地出现吗?"和 "如果它发生了,在软件中是否有任何具体的需要或可以做的事情?" 如果这两个问题的答案都是 "是",那么你就应该把这种情况作为一种异常来处理;否则,你就应该把这种情况作为一个错误来处理 。

经验总结扩展阅读