我尝试在谷歌上搜索并阅读了一些片段。为什么Ada是一种“安全关键”语言?我注意到的一些事情包括:
- 没有指针
- 指定范围(此类型是整数,但只能为1-12)
- 明确声明函数参数是否为out或in/out
- 基于范围的循环(避免边界错误或边界检查)
我对其余的语法要么不理解,要么不知道它如何帮助它成为“安全关键”的语言。这些都是一些点,但我没有看到大局。它是否具有我没有看到的设计契约?它是否有使代码更难编译的规则(如果有,是什么规则)?为什么它是一种“安全关键”的语言?
我尝试在谷歌上搜索并阅读了一些片段。为什么Ada是一种“安全关键”语言?我注意到的一些事情包括:
我对其余的语法要么不理解,要么不知道它如何帮助它成为“安全关键”的语言。这些都是一些点,但我没有看到大局。它是否具有我没有看到的设计契约?它是否有使代码更难编译的规则(如果有,是什么规则)?为什么它是一种“安全关键”的语言?
这很简单。Ada语法中有很多似乎与使语言“安全关键”(无论对于一种语言来说这意味着什么)没有什么关系的原因是,这不是Ada的设计目标。它被设计为一种通用的编译系统编程语言,足够强大,以至于美国国防部可以摆脱所有需要支持各地小型一次性语言的问题。
最终结果是一个相当适用于安全关键应用程序的语言,这只是因为 该语言设计得非常出色,考虑到军事应用程序(在这里软件可靠性通常涉及到生命危险)。
惊人的是,很少有其他现代语言将建立可靠的软件作为设计目标。 大多数语言似乎是由一个孤独的“天才”黑客创造的,其主要目标是能够快速产生大量的代码,也许是以某种黑客喜欢的新方式。
generic
type Item is private;
package Stacks is
type Stack is private;
function Is_Empty(S: Stack) return Boolean;
function Is_Full(S: Stack) return Boolean;
procedure Push(S: in out Stack; X: in Item)
with
Pre => not Is_Full(S),
Post => not Is_Empty(S);
procedure Pop(S: in out Stack; X: out Item)
with
Pre => not Is_Empty(S),
Post => not Is_Full(S);
Stack_Error: exception;
private
-- Private portion.
end Stacks;
Null
的能力; 这很有用,因为您可以a)在子程序参数中指定该排除条件,b)简化算法[因为您不必在每个使用实例中检查null],并且c)让异常处理程序处理(我假设是)异常情况下的Null
。AdaCore在这里对Ada 2005的各种安全功能进行了精彩的介绍:
http://www.adacore.com/knowledge/technical-papers/safe-secure/
美国政府和行业也曾经进行过有关程序可靠性的研究,比较了各种编程语言。由于这些网站都很老,我没能快速找到其中一篇,但下面是DDCI网站上的引用:“在八十年代进行的研究中,Ada始终优于像Pascal、Fortran和C等已有的编程语言。在九十年代,Ada在衡量能力、效率、维护、风险和生命周期成本等方面仍然胜过C++。”
在以下链接中列出了Commanche项目选择Ada的原因。我想补充的是,平台实现已经存在很长时间并保持稳定。正如文章中的一位消息来源所说,维护是成本的主要来源。我们已经看到现代竞争者.NET和Java不断变化。 Ada的长期稳定性对于常常需要投入使用几十年的安全关键应用程序来说更为重要。
http://www.ddci.com/displayNews.php?fn=programs_rah66.php
另一个好处是Ada被设计用于跨语言开发。我不断看到新闻中的人们谈论.NET和JVM如何创新,因为它们让您将“正确的工具用于正确的工作”混合到一个系统中。 Ada已经有这种能力很长一段时间了。应用程序常常是Ada、C、C++、汇编等的混合体(例如MULTOS CA)。而且它们仍然运行良好。
Ada也没有停滞不前。他们不断更新语言,最近在2012年进行了更新。它的可移植性使其能够运行在JVM和.NET上,以便那些想要库或者已经有大量现有代码的人使用。还有来自IBM、Aonix、AdaCore和Green Hills的Ada开发工具和强大的运行时环境,适用于许多操作系统和实时操作系统。
最后一个好处:如果它能编译通过,那么它将能够正常运行。通常来说。
我知道这有点晚了,但这是我最近遇到的一个例子。我写了下面这个 C++ 函数,在 -O0
下工作得很好:
size_t get_index(const Monomial & t, const Monomial & u) {
get_index(t, u.log()); // forgot to type "return" first...
}
-O0
编译它时,它居然奇迹般地运行良好。但是当我使用-O3
编译它时,它每次都崩溃了,而我却找不出原因,因为我没有看到警告(如果有的话)。试想当你认为在那里应该有一个return
语句时,你还需要进行调试。int a;
scanf("%d", a); /* left out & before the a */
int
作为指针或反之的做法被认为是常规编程实践,以至于25年前的编译器甚至不会发出警告。这是C语言的一个特性,而不是缺陷。(例如,参见Brian Kernaghan的"Why Pascal is not my favorite Language")。当然,在那个时候,家用计算机操作系统没有内存保护;如果你很幸运,当计算机重启时,它没有写入硬盘。
这些错误在Ada中甚至无法编译。函数必须返回值,而你不能意外地使用Integer
代替access Integer
(即指向整数的指针)。
这只是个开始!