我知道在Ada开发时期,GC并不受欢迎,而且对于嵌入式编程的主要用例,它仍然不是一个好的选择。
但考虑到Ada是一种通用编程语言,为什么后续版本的语言和编译器实现中没有引入部分和可选的(只跟踪显式标记内存对象)垃圾收集器呢?
我简直无法想象开发一个正常的桌面应用程序而没有垃圾收集器。
我知道在Ada开发时期,GC并不受欢迎,而且对于嵌入式编程的主要用例,它仍然不是一个好的选择。
但考虑到Ada是一种通用编程语言,为什么后续版本的语言和编译器实现中没有引入部分和可选的(只跟踪显式标记内存对象)垃圾收集器呢?
我简直无法想象开发一个正常的桌面应用程序而没有垃圾收集器。
Ada的设计初衷是用于军事应用。其设计中的一个重点是确定性,即希望Ada程序在任何环境、所有操作系统下都能够始终如一地运行。
垃圾回收器会将一个应用程序变成两个互相对抗的程序。Java程序会在GC决定工作时随机出现卡顿,如果GC处理得过慢,有时会发生内存不足而有时不会。
简而言之:垃圾收集器引入了程序设计者不希望出现的一些变量。制造混乱--清理它!同样的代码,每次都表现相同。
并不是说Ada成为了全球疯狂的成功。
malloc
在需要将小块内存重新组合成大块内存时,也有类似于Java(和其他语言)垃圾回收器的“抽搐”模式,以类似于非确定性的方式进行。分配/释放的便利性总是要付出代价的。 - Darkhogg首先,语言本身并没有真正“禁止”垃圾回收。
其次,一些实现确实执行垃圾回收。特别是,所有针对JVM的实现都进行垃圾回收。
第三,所有编译器都有一种方式来获取一定数量的垃圾回收。你看,当访问类型超出范围时,如果你明确告诉语言为其对象分配一定的存储空间,则该空间将在此时被销毁。我过去曾使用过这个方法来获得一定程度的垃圾回收。你需要使用声明式语法:
type Foo is access Blah;
for Foo'storage_size use 100_000_000; --// 100K
首先,我想知道现在谁在使用Ada。我实际上喜欢这种语言,甚至还有一个针对Linux/Ada的GUI库,但是多年来我没有听到任何关于活跃的Ada开发的消息。由于其与军方的联系,我真的不确定它是否是古代历史,或者是如此成功以至于所有关于它的使用都是机密的。
我认为Ada没有垃圾回收的原因有几个。首先,它的诞生年代是大多数编译语言主要使用堆栈或静态内存,或者在一些情况下显式堆分配/释放的时代。 GC作为一种通用哲学真正流行起来是在1990年左右,当OOP、改进的内存管理算法和足够强大以节省运行所有内容所需的循环的处理器开始发挥作用时。仅仅将Ada编译就足以使1989年的IBM 4331大型机无法承受。现在,我的手机可以超越那台机器的CPU。
另一个好的原因是,有人认为严格的程序设计包括对内存资源的精确控制,并且不应容忍让动态获取的对象漂浮。可悲的是,随着动态内存越来越成为规则,太多的人最终会泄漏内存。此外,就像汇编语言相对于高级语言的“效率”,以及原始JDBC相对于ORM系统的“效率”一样,手动内存管理的“效率”在扩展时往往会逆转(我见过ORM基准测试,其中JDBC相当于只有一半的效率)。虽然这可能违反直觉,但现在的系统在全局优化大型应用方面要好得多,而且能够针对表面上微小的变化做出彻底的重新优化,包括根据检测到的负载实时重新平衡算法。你的问题是不正确的。它确实有用。请参见 ada.finalization 包,它可以为您处理垃圾回收。
我想分享一个非常简单的示例,演示如何实现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;