Ada中的例外是确定性的。 (但是一些可以引发异常的检查有一些自由。如果编译器可以提供正确的答案,那么如果中间结果超出了相关类型的范围,则不一定要引发异常。)
至少一个Ada编译器(GNAT)具有“零成本”异常实现。这不会使异常完全免费,但在实际引发异常之前,您不需要支付运行时成本。您仍然需要在代码空间方面支付费用。这个成本有多大取决于架构。
我自己没有研究安全关键系统,但我确信Ariane 4惯性导航系统中用于软件的运行时间包括异常。
如果您不想要例外,一种选择是使用SPARK(一种源自Ada的语言)。您仍然可以使用任何您喜欢的Ada编译器,但是您使用SPARK工具来证明程序不会引发任何异常。你应该注意到SPARK并不神奇。您必须通过插入断言来帮助这些工具,这些工具可以用作证明的中间步骤。
有嵌入式系统是安全或关键任务的,嵌入式系统是硬实时的,嵌入式系统是两者兼而有之。
实时硬实时的嵌入式系统可能受到限制。 70年代,同事们在导弹制导系统上工作,在主回路中有大约4个指令值! (你可以想象,它是用汇编语言编写的,并使用了一个调优的执行程序,而不是RTOS。不支持异常)。另一方面,我工作的最后一个,在1 GHz PowerPC板上,对特定中断的响应有2毫秒的最后期限,我们测得的最坏情况是1.3毫秒(无论如何这是一个软实时要求,你不必连续错过太多)。
该系统也有安全要求(我知道,我知道,安全的导弹系统,呵呵)虽然我们被允许使用例外,但未处理的例外意味着系统必须关闭,导弹在飞行中或没有,导致损失导弹我们严格禁止说 when others => null; 吞下一个异常,所以我们没有处理的任何异常将被“未处理”并且会反弹到最高级别。
when others => null;
参数是,如果发生未处理的异常,您将无法再知道系统的状态,因此您无法证明继续存在。当然,更广泛的安全工程必须考虑整个系统应该采取什么行动(例如,这个处理器可能应该以恢复模式重新启动)。
有时人们将异常作为其控制流程的一部分;事实上,对于处理随机文本输入,一个常用的方法是,而不是检查文件的结尾,只需继续,直到你得到一个 End_Error ;
End_Error
loop begin -- read input -- process input exception when End_Error => exit; end; end loop;
雅各布的回答 讨论使用SPARK。您不必使用SPARK来处理异常,但当然能够向您自己(以及您的安全审核员证明!)证明不会有任何异常。处理异常非常棘手,有些RTS(例如 Cortex GNAT RTS ) 别;配置编译指示
pragma Restrictions (No_Exception_Propagation);
意味着异常无法传播到它们被引发的范围之外(程序将通过调用a来崩溃) Last_Chance_Handler )。
Last_Chance_Handler
仅仅在它们被引发的范围内传播异常不是,IMO,这是有用的:
begin -- do something if some error condition then raise Err; end if; -- do more exception when Err => null; end;
避免“多做”代码会是一种相当混乱的方式。最好使用标签!