代码之家  ›  专栏  ›  技术社区  ›  Lothar

为什么艾达没有垃圾收集器?

  •  11
  • Lothar  · 技术社区  · 16 年前

    我知道GC在开发Ada的时候并不流行,对于嵌入式编程的主要用例来说,它仍然不是一个好的选择。

    但是考虑到Ada是一种通用编程语言,为什么在后来的语言版本和编译器实现中没有引入部分和可选(只跟踪显式标记的内存对象)垃圾收集器呢?

    我实在想不出在没有垃圾收集器的情况下再开发一个普通的桌面应用程序。

    7 回复  |  直到 10 年前
        1
  •  31
  •   Carl Smotricz    16 年前

    ADA的设计考虑到了军事应用。它的设计中的一个重要优先事项是确定性。也就是说,在任何环境下,在所有操作系统下,人们都希望ADA程序始终以完全相同的方式执行……有点像。

    垃圾收集器将一个应用程序转换为两个应用程序,彼此进行工作。当GC决定去工作时,Java程序会在随机的时间间隔内发生打嗝,如果它太慢,那么应用程序有时会耗尽堆而不是其他的。

    简化:垃圾收集器在程序中引入了一些设计者不想要的可变性。你弄得一团糟-你把它打扫干净!相同的代码,每次都有相同的行为。

    注意,不是说Ada在世界范围内取得了巨大的成功。

        2
  •  13
  •   T.E.D.    16 年前

    因为ADA设计用于实时控制武器的防御系统,垃圾收集会干扰应用程序的时间安排。这是危险的,这就是为什么多年来,Java发出警告说它不被用于医疗和军事控制系统。

    我相信,不再有这种对Java的免责声明是因为底层硬件已经变得更快,而且Java有更好的GC算法和更好的GC控制。

    请记住,ADA是在20世纪70年代和80年代开发的,当时的计算机远不如现在的强大,在控制应用程序中,时间问题至关重要。

        3
  •  5
  •   Matt    10 年前

    答案更复杂:由于实时约束等原因,Ada不需要垃圾收集器。然而,该语言已经被巧妙地设计为允许实现垃圾收集器。

    尽管许多(几乎所有)编译器不包括垃圾收集器,但有一些值得注意的实现:

    • a patch for GNAT
    • 针对Java虚拟机的艾达编译器(我不知道这些项目是否仍然被支持)。它使用了JVM的垃圾收集器。

    在Ada中,还有很多其他的垃圾收集来源。这个话题一直在讨论,主要是因为90年代中期与Java的激烈竞争。 this page : "Ada 95 is what the Java language should have been" 当Java是“下一件大事”之前,微软吸引了C。

        4
  •  4
  •   T.E.D.    15 年前

    首先,语言中没有真正的 禁止 垃圾收集。

    其次是一些实施 执行垃圾收集 . 尤其是针对JVM垃圾收集的所有实现。

    第三, 有一种方法可以收集一定数量的垃圾 所有编译器。你看,当一个入口 类型 超出范围,如果您专门告诉语言留出一定数量的空间来存储其对象,那么该空间将在此时被破坏。我过去用这个来收集垃圾。你使用的伏都教宣言是:

    type Foo is access Blah;
    for Foo'storage_size use 100_000_000; --// 100K
    

    如果这样做,那么当foo类型超出作用域时,所有(100k)分配给foo指针指向的blah对象的内存都将被清除。由于ADA允许您将子例程嵌套在其他子例程中,因此这一功能特别强大。

    要了解有关存储池大小和存储池可以为您做什么的更多信息,请参阅 LRM 13.11

    第四,编写良好的ADA程序不像C程序那样依赖动态内存分配。C有许多设计孔,练习者学会了用指针画画。很多这样的成语在《美国残疾人法案》中并不重要。

        5
  •  0
  •   Tim Holloway    16 年前

    首先,我想知道这些天谁在使用ADA。实际上,我喜欢这种语言,甚至还有一个用于Linux/ADA的GUI库,但多年来我都没有听说过任何关于主动ADA开发的内容。由于它的军事联系,我真的不确定它是古老的历史还是如此的成功以至于所有提到它的用途都是机密的。

    我认为在ADA中没有GC有几个原因。首先,也是最重要的,它可以追溯到一个时代,大多数编译语言主要使用堆栈或静态内存,或者在少数情况下使用显式堆分配/释放。GC作为一种通用的哲学,真正开始于大约1990年左右,当时OOP,改进的内存管理算法和处理器,其强大程度足以让运行它的周期空闲下来,它们都形成了自己的体系。在1989年,简单地编译ADA就可以对IBM4331大型机做什么,这简直是无情的。现在我有了一部比那台机器的CPU性能更好的手机。

    另一个很好的原因是,有些人认为严格的程序设计包括对内存资源的精确控制,并且不应该容忍动态获取的对象浮动。遗憾的是,随着动态内存越来越成为规则,最终有太多人泄漏了内存。另外,像汇编语言在高级语言上的“效率”和原始JDBC在ORM系统上的“效率”一样,手工内存管理的“效率”随着规模的扩大而趋向于反转(我见过ORM基准测试,其中JDBC等价物的效率只有一半)。我知道,这是违反直觉的,但现在的系统在全局优化大型应用程序方面做得更好,而且它们能够针对细微的变化进行彻底的重新优化。包括根据检测到的负载动态地动态地重新平衡算法。

    恐怕我会和那些说实时系统负担不起GC内存的人有所不同。GC不再是每隔几分钟就冻结整个系统的东西。现在我们有更聪明的方法来恢复记忆。

        6
  •  0
  •   Wossname    10 年前

    我想我将分享一个非常简单的例子,说明如何实现一个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将把分配的整数返回到存储池(用C语言称为heap)。您可以使用valgrind来证明这实际上可以防止4个字节的内存泄漏。

    Ada.unchecked_deallocation(一个一般定义的过程)可以用于(我认为)任何可以使用“new”关键字分配的类型。ADA参考手册(“13.11.2未检查的存储解除分配”)有更多详细信息。

        7
  •  -1
  •   Alex.F    15 年前

    你的问题不正确。是的。请参阅为您处理gc的包ada.finisation。