Listing 1 shows the simple embedded systems-friendly assertions that I’ve found adequate for a wide range of embedded projects. Listing 1 is similar to the standard <assert.h>
(<cassert>
in C++), except that the solution shown in Listing 1:
- allows customizing the error response;
- conserves memory by avoiding proliferation of multiple copies of the filename string;
- provides additional macros for testing and documenting preconditions (
REQUIRE
), postconditions (ENSURE
), and invariants (INVARIANT
). (The names of the three last macros are a direct loan from Eiffel, the programming language that natively supports DbC.)
ASSERT()
macro (lines 28-29 of Listing 1) is very similar to the standard assert()
. If the argument passed to this macro evaluates to 0 (false), and if additionally the macro NASSERT
is not defined, then ASSERT()
will invoke a global callback onAssert__()
. The function onAssert__()
gives the clients the opportunity to customize the error response when the assertion fails. In embedded systems, onAssert__()
typically first monopolizes the CPU (by disabling interrupts), then possibly attempts to put the system in a fail-safe mode, and eventually triggers a system reset. (Many embedded systems come out of reset in a fail-safe mode, so putting them in this mode before reset is often unnecessary.) If possible, the function should also leave a trail of bread crumbs from the cause, perhaps by storing the filename and line number in a nonvolatile memory. (The entry to onAssert__()
is also an ideal place to set a breakpoint if you work with a debugger. TIP: Consult your debugger manual on how you can hard-code a permanent breakpoint in onAssert__()
.)Compared to the standard assert(), the macro ASSERT() conserves memory (typically ROM) by passing
THIS_FILE__
(Listing 1, line 26) as the first argument to onAssert__()
, rather than the standard preprocessor macro __FILE__
. This avoids proliferation of the multiple copies of the __FILE__
string but requires invoking macro DEFINE_THIS_FILE
(line 25), preferably at the top of every C/C++ file.2Defining the macro
NASSERT
(Listing 1, line 7) disables checking the assertions. When disabled, the assertion macros don’t generate any code (lines 10 and 35-37); in particular, they don’t test the expressions passed as arguments, so you should be careful to avoid any side effects (required for normal program operation) inside the expressions tested in assertions. The notable exception is the ALLEGE() macro (lines 11 and 31), which always tests the expression, although when assertions are disabled, it does not invoke the onAssert__()
callback. ALLEGE()
is useful in situations where avoiding side effects of the test would require introducing temporaries, which involves pushing additional registers onto the stack—something you often want to minimize in embedded systems.以上比较简单,不翻译了The DbC PhilosophyDbC的哲学/理念
The most important point to understand about software contracts (assertions in C/C++) is that they neither handle nor prevent errors, in the same way as contracts between people do not prevent fraud. For example, asserting successful memory allocation:
ALLEGE((foo = new Foo) != NULL)
, might give you a warm and fuzzy feeling that you have handled or prevented a bug, when in fact, you haven’t. You did establish a contract, however, in which you spelled out that the inability to dynamically allocate object Foo at this spot in the code is an error. From that point on, the contract will be checked automatically and sure enough, the program will brutally abort if the contract fails. At first, you might think that this must be backwards. Contracts not only do nothing to handle (let alone fix) bugs, but they actually make things worse by turning every asserted condition, however benign, into a fatal error! However, recall from the previous discussion that the first priority when dealing with bugs is to detect them, not to handle them. To this end, a bug that causes a loud crash (and identifies exactly which contract was violated) is much easier to find than a subtle one that manifests itself intermittently millions of machine instructions downstream from the spot where you could have easily detected it.
经验总结扩展阅读
- 烈火军校女二是谁?
- 小晴天第几集出场?
- 我家小两口装修是哪一期?
- 古代环保部门叫啥
- 耶稣是虚构还是真实
- 《英雄联盟》英雄亚索怎么玩(各个英雄如何评价亚索)
- 张译喝拉菲是第几集?
- 电视剧烈火军校谁是反派?
- 唐僧会武功的动漫叫什么?
- MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选