我知道GC在Ada开发的时代并不受欢迎,对于嵌入式编程的主要用例,它仍然不是一个好的选择。
但是考虑到Ada是一种通用编程语言,为什么不是部分和可选的(仅跟踪显式标记的内存对象)垃圾收集器在后来的语言版本和编译器实现中引入。
我根本无法想到在没有垃圾收集器的情况下开发普通的桌面应用程序。
答案 0 :(得分:31)
Ada的设计考虑了军事应用。其设计的一个重要优先事项是决定论。也就是说,人们希望Ada程序在任何环境下,在所有操作系统下,每次都能以完全相同的方式运行......那种事情。
垃圾收集器将一个应用程序转换为两个,相互作用。当GC决定开始工作时,Java程序会以随机的间隔产生打嗝,如果它的速度太慢,那么应用程序有时会耗尽堆而不是其他应用程序。
简化:垃圾收集器将一些可变性引入设计者不想要的程序中。你搞得一团糟 - 你清理它!相同的代码,每次都有相同的行为。
并不是说Ada在全球取得了成功,请注意。
答案 1 :(得分:13)
因为Ada设计用于实时控制武器的防御系统,垃圾收集会干扰您的应用程序的时间安排。这很危险,这就是为什么多年来Java一直警告说它不能用于医疗和军事控制系统。
我认为不再存在Java的这种免责声明的原因是因为底层硬件变得更快,以及Java具有更好的GC算法和更好地控制GC的事实。
请记住,Ada是在20世纪70年代和80年代开发的,当时计算机的功能远远不如今天,而且在控制应用中,计时问题至关重要。
答案 2 :(得分:5)
答案更复杂:Ada不需要垃圾收集器,因为实时约束等。但是,该语言设计巧妙,以便实现垃圾收集器。
尽管许多(几乎所有)编译器都没有包含垃圾收集器,但有一些值得注意的实现:
网络上有很多关于垃圾收集的其他来源。这个主题已经详细讨论过了,主要是因为90年代中期与Java的激烈竞争(看看this page:"Ada 95 is what the Java language should have been"
),当时Java是微软之前的“下一件大事”画了C#。
答案 3 :(得分:4)
首先,语言中没有任何内容确实禁止垃圾收集。
其次一些实现执行垃圾收集。特别是,所有针对JVM垃圾收集的实现。
第三,有一种方法可以与所有编译器进行一些垃圾收集。您会看到,当访问类型超出范围时,如果您特意告诉语言留出一定数量的空间来存储其对象,那么该空间将在该点被销毁。我过去用过这个来获得一些垃圾收集。您使用的声明voodo是:
type Foo is access Blah;
for Foo'storage_size use 100_000_000; --// 100K
如果这样做,那么当Foo类型超出范围时,将清除分配给Foo指针指向的Blah对象的所有(100K)内存。由于Ada允许您将子例程嵌套在其他子例程中,因此这非常强大。
要详细了解storage_size和存储池可以为您做什么,请参阅LRM 13.11
第四,精心编写的Ada程序几乎不像C程序那样依赖动态内存分配。 C有许多设计漏洞,实践者学习使用指针绘画。在Ada中,很多这些成语都不是必需的。
答案 4 :(得分:0)
首先,我想知道这些天谁在使用Ada。我实际上喜欢这种语言,甚至还有一个用于Linux / Ada的GUI库,但我多年来都没有听说过有关Ada开发的任何内容。由于它的军事联系,我真的不确定它是否是古老的历史,或者是如此成功,以至于所有提及它的使用都被归类。
我认为Ada中没有GC的原因有两个。首先,它最重要的是,它可以追溯到大多数编译语言主要使用堆栈或静态内存的时代,或者在少数情况下,显式堆分配/免费。作为一般哲学的GC实际上只在大约1990年左右起飞,当OOP,改进的内存管理算法和强大的处理器足以使循环运行它们全部进入他们自己。简单编译Ada可以在1989年对IBM 4331大型机进行简单无情的处理。现在我的手机可以胜过该机器的CPU。
另一个很好的理由是,有些人认为严格的程序设计包括对内存资源的精确控制,并且不应该允许动态获取的对象浮动。可悲的是,由于动态内存越来越成为规则,太多人最终泄露内存。另外,就像汇编语言相对于高级语言的“效率”,以及原始JDBC相对于ORM系统的“效率”而言,手动内存管理的“效率”随着它的扩展而趋于反转(我已经看到了ORM基准测试)其中JDBC等效的效率只有一半)。我知道,反直觉,但是现在系统在全局优化大型应用程序方面要好得多,而且它们能够根据表面上的微小变化进行彻底的重新优化。包括基于检测到的动态重新平衡算法负荷。
我担心我不得不与那些说实时系统无法负担GC内存的人不同。 GC不再是每隔几分钟冻结整个系统的东西。这些天我们有更聪明的方法来回收记忆。
答案 5 :(得分:0)
我以为我分享了一个如何实现Free()过程的简单示例(将以所有C程序员熟悉的方式使用)...
with Ada.Integer_Text_IO, Ada.Unchecked_Deallocation;
use Ada.Integer_Text_IO;
procedure Leak is
type Int_Ptr is access Integer;
procedure Free is new Ada.Unchecked_Deallocation (Integer, Int_Ptr);
Ptr : Int_Ptr := null;
begin
Ptr := new Integer'(123);
Free (Ptr);
end Leak;
在程序结束时调用Free会将分配的Integer返回到存储池("堆"用C表示)。您可以使用valgrind来证明这确实可以防止4个字节的内存泄露。
Ada.Unchecked_Deallocation(一般定义的程序)可用于(我认为)可以使用" new"分配的任何类型。关键词。 Ada参考手册(" 13.11.2未经检查的存储重新分配")有更多详细信息。
答案 6 :(得分:-1)
您的问题不正确。确实如此。请参阅为您处理GC的包ada.finalization。