带手动内存管理的口译语言?

时间:2010-01-25 16:51:07

标签: memory memory-management programming-languages interpreter

哪种解释语言无指针语言(IE:Python,Java,Perl,PHP,Ruby,Javascript等)都有手动内存管理?我不记得曾经听过一个。

解释语言的主要问题不是垃圾收集的非确定性延迟(或没有足够延迟时的空间复杂性)吗?那么为什么不写一些与Java完全相同的东西,但强制你手动释放内存呢?

修改

手动内存管理的意思是该语言会引用对象,您可以使用引用删除该对象。

示例:

Object a = new Object(); // a is a reference to the object
Object b = a; // b is a reference to the same object
a.method(); // fine
delete b; // delete the object referenced by b
a.method(); // null dereference exception

那么在这样的语言中会出现什么警告(除了内存泄漏)?

9 个答案:

答案 0 :(得分:19)

问题背后的前提有点狡猾:

  • 内存模型语言的属性,而不是其实现。

  • 被解释是实现的属性,而不是语言。

示例:

  • 编程语言Scheme具有自动内存管理功能,它有许多解释实现,还有一些优秀的本机代码编译器,包括Larceny,Gambit和PLT Scheme(包括 both 解释器和JIT编译器进行无缝转换。

  • 编程语言Haskell具有自动内存管理功能;两个最着名的实现是解释器HUGS和编译器GHC。在编译到本机代码(yhc)和解释(Helium)之间,还有其他几个可敬的实现分开。

  • 编程语言C具有手动内存管理功能,虽然世界上充满了C编译器,但我们这些已经足够记住80年代辉煌的人可能会记得Saber-C或C-terp,两个非常有用的C语言解释器对于MS-DOS。

然而,你的问题背后有一个真实的观察:手动内存管理的语言通常是编译的。为什么呢?

  • 手动内存管理是一项传统功能,通常用于与旧代码兼容。传统语言通常已经足够成熟,可以使用本机代码编译器。

  • 许多新语言由实现定义。构建解释器比构建编译器更容易。在解释器中实现简单的自动内存管理比在本机代码编译器中实现高性能自动内存管理更容易。因此,如果语言从其第一个实现中获得定义,则自动内存管理与解释相关联,因为在解释的设置中,实现更容易。

  • 手动内存管理也(有时甚至是合理的)用于提高性能。 Ben Zorn在20世纪90年代的优秀实验研究表明,自动内存管理与手动内存管理一样快或快,但需要大约两倍的内存。因此,手动内存管理通常用于内存稀缺的非常小的设备上,而在非常大的数据中心中,内存加倍是昂贵的。 (它有时也被那些对内存管理知之甚少的人使用,但是他们听说垃圾收集很慢。他们在1980年是正确的。)当对性能有顾虑时,你通常会找到一个本机代码编译器而不是而不是口译员。

    一些非常有趣的例外也来自这个原则。例如,FORTH和第一个PostScript实现都设计为在内存资源稀缺的小型嵌入式设备(望远镜和打印机)上运行,但计算时间不是一个因素。这两种语言最初都是使用比本机代码更紧凑的字节码实现的,并且都具有手动内存管理功能。所以:手动内存管理的解释器。 (PostScript的更高版本添加了垃圾收集选项。)

总结:

  • 自动与手动内存管理是语言

  • 编译与解释是实施

  • 原则上这两个选项可以正交,但出于实用工程原因,自动内存管理通常与解释相关

    < / LI>
  

解释语言的主要问题不是垃圾收集的非确定性延迟(或没有足够延迟时的空间复杂性)吗?

我不知道 是关于编程语言的解释实现的主要问题。按字母顺序排列,Lua,Perl,PostScript,Python和Ruby都非常成功,Icon,Scheme和Squeak Smalltalk都取得了一定的成功。唯一不可预知的延迟引起关注的领域是硬实时计算,例如控制汽车刹车的ABS系统(如果你驾驶的是一辆足够漂亮的汽车)。


在编辑问题后添加注释:您将“已解释”更改为“无指针”。但您在评论中说,您的意思是询问有newdelete的语言。 newdelete的任何语言都有指针:根据定义,new返回的是指针。 (在某些语言中,也可能有其他指针源。)所以我认为你的意思是“没有指针算术且没有地址操作符的语言”。

答案 1 :(得分:4)

Forth堆叠了可以使用FORGET释放的内存区域。

答案 2 :(得分:4)

  

哪种解释语言有手动内存管理?我不记得曾经听过一个。

没有解释语言这样的东西。语言既不编译也不解释。只有的语言是。语言是一堆抽象的数学规则。解释或编译是语言实现的特征,他们没有与语言有关。 每种语言都可以由编译器或解释器实现;大多数现代高性能语言实现实际上使用两者并在它们之间切换,具体取决于哪一个在特定上下文中更快。

C是编译语言吗?那里有C语言翻译。 Python是一种解释型语言吗?所有8个当前的Python实现都使用编译器。

因此,由于每种语言都可以具有解释的实现,因此C和C ++是具有手动内存管理的解释语言的示例。 (而且这不仅仅是理论上的分裂竞赛,实际上是 C&C ++解释器.VxWorks实时操作系统甚至在内核中包含一个权限,而NASA曾经使用过这个解释器在航天器上修复有缺陷的内核模块。)

另一个例子是1958年的第一个Lisp版本:它具有手动内存管理(基于引用计数),但仅在几个月后更换为具有自动内存管理的版本,它已使用自从。虽然再次使用编译器或解释器可以实现任何语言,所以我不知道该版本是否具有解释的实现或编译的实现。 (事实上​​,我不确定它是否已实现所有。)

如果你稍微放松一下标准,并意识到内存管理只是一般资源管理的一个特例,那么你会发现几乎所有的所有语言,无论你是否想要称它们编译或完全解释或其他东西,至少为某种类资源(文件句柄,数据库连接,网络连接,缓存......)提供某种形式的手动资源管理。

答案 3 :(得分:2)

在某些高性能解释语言(如Lua)中,您可以手动处理垃圾回收。请参阅lua_gc

答案 4 :(得分:2)

有一些C / C ++解释器可用,例如,this one

我自己没试过,但我认为因为它声称与编译的C / C ++兼容,所以需要进行“手动”内存管理。

答案 5 :(得分:1)

原因是循环引用,空指针异常和多个引用。一个简单的例子:

var a = new Object();
var b = a;
a = null;//or delete a or free a or whatever;
print(b);//what now? is b null? or is b still new Object()?

如果在上面的示例中,b现在为null,则在重新定义变量时会出现一些主要问题。例如,如果将a设置为c,该怎么办? b也会是c吗?

您可以阅读其他问题,例如circular references, on wikipedia

答案 6 :(得分:1)

回答这部分问题:

  

不是主要关注的问题   解释语言   非确定性延迟(或空间   没有足够的复杂性   延迟)垃圾收集?所以为什么   不只是写一些完全相同的东西   Java,但强迫你释放内存   手动?

这可能是某些系统的问题。对其他系统而言,问题并非如此。使用垃圾收集运行的软件可以比仅调用malloc的系统更快地分配内存。当然,你最终会在GC时间支付时间。

以基于网络的系统为例。您可以在处理请求期间分配所有内存,然后GC可以收集。它可能不会像那样结束,但你明白了。

垃圾收集有很多不同的策略。哪种策略最适合系统将取决于要求。但即使你需要绝对决定论,你也可以使用:Realtime Java

答案 7 :(得分:0)

解释并不一定意味着垃圾回收。 Perl,Tcl,Python等等。我相信所有人都使用简单的引用计数,所以内存回收是确定性的,虽然根本不透明(在Perl程序上曾经尝试strace吗?)。

答案 8 :(得分:0)

Python的API通常允许打开或关闭延迟的垃圾收集 - 查看标准库“gc”模块上的文档:

http://docs.python.org/library/gc.html

但与静态语言相比,这并不是什么原因让它变慢 - 数据本身的动态特性是导致速度差异的主要因素。