我正在设计一种语言.首先,我想决定要生成什么代码.该语言将具有类似于javascript的词法闭包和基于原型的继承.但我不是gc的粉丝,尽量避免.所以问题是:有没有一种优雅的方法来实现闭包而不需要在堆上分配堆栈帧并将其留给垃圾收集器?
我的第一个想法:
使用引用计数和垃圾收集周期(我真的不喜欢这个)
使用意大利面条堆栈(看起来非常低效)
限制闭包形成某些上下文,这样我就可以使用返回地址堆栈和本地堆栈.
我不会使用高级语言或遵循任何调用约定,所以我可以尽可能多地粉碎堆栈.
(编辑:我知道引用计数是垃圾收集的一种形式,但我使用gc的更常见的含义)
如果您可以通过不使用GC来解释您要避免的内容,那么这将是一个更好的问题.我确信你知道,大多数提供词法闭包的语言都会在堆上分配它们,并允许它们在创建它们的激活记录中保留对变量绑定的引用.
我所知道的唯一替代方法是gcc
嵌套函数的用途:为函数创建一个trampoline并将其分配到堆栈中.但正如gcc手册所说:
如果你试图在包含函数退出后通过其地址调用嵌套函数,那么所有的地狱都会破裂.如果您尝试在包含范围级别退出后调用它,并且如果它引用了一些不再在范围内的变量,那么您可能会很幸运,但冒风险并不明智.但是,如果嵌套函数没有引用超出范围的任何内容,那么您应该是安全的.
简短版本是,您有三个主要选择:
在堆栈上分配闭包,并且在包含函数退出后不允许使用它们.
在堆上分配闭包,并使用某种垃圾收集.
做原创研究,也许从ML,Cyclone等地区的东西开始.
这个主题可能会有所帮助,尽管这里的一些答案已经反映了答案.
一张海报很有用:
在没有真正的垃圾收集的情况下,似乎你想要关闭垃圾收集.请注意,闭包可用于实现cons单元格.所以你的问题似乎是关于垃圾收集"在没有真正的垃圾收集" - 有丰富的相关文献.限制问题到闭包并没有真正改变它.
所以答案是:不,没有优雅的方法来关闭和没有真正的GC.你可以做的最好的是一些黑客攻击,以限制你的闭合到特定类型的闭合.如果你有一个合适的GC,这一切都是不必要的.
所以,我的问题反映了其他一些 - 为什么你不想实现GC?简单的标记+扫描或停止+复制需要大约2-300行(Scheme)代码,并且在编程工作方面并不是那么糟糕.在使程序变慢方面:
您可以实现更复杂的GC,它具有更好的性能.
想想你所用的所有内存泄漏程序都不会受到影响.
使用GC进行编码是一种祝福.(想想C#,Java,Python,Perl等......与C++或C相比).
我明白我已经很晚了,但我偶然偶然发现了这个问题.
我认为完全支持闭包确实需要GC,但在某些特殊情况下,堆栈分配是安全的.确定这些特殊情况需要进行一些逃逸分析.我建议你看一下BitC语言文章,比如BitC中的Closure Implementation.(虽然我怀疑这些文件是否反映了当前的计划.)BitC的设计者也遇到了同样的问题.他们决定为编译器实现一种特殊的非收集模式,它拒绝所有可能逃脱的闭包.如果启用,则会显着限制语言.但是,该功能尚未实现.
我建议你使用收藏家 - 这是最优雅的方式.您还应该考虑一个构建良好的垃圾收集器比malloc更快地分配内存.BitC人员确实非常重视性能,他们仍然认为即使对于他们的操作系统Coyotos的大多数部分,GC都很好.您可以通过简单的方式迁移缺点:
只创造最少量的垃圾
让程序员控制收集器
通过转义分析优化堆栈/堆使用
使用增量或并发收集器
如果可能的话,像Erlang那样划分堆
许多人担心垃圾收集器因为他们使用Java的经验.Java有一个很棒的收集器,但是用Java编写的应用程序由于产生了大量的垃圾而存在性能问题.此外,由于启动和响应时间较长,对于桌面应用程序来说,膨胀的运行时和花哨的JIT编译并不是一个好主意.