【问题标题】:Implementing destructors in generated C code在生成的 C 代码中实现析构函数
【发布时间】:2011-06-29 08:49:14
【问题描述】:

假设我有时想编写一个编译器,为以下语言生成 C 代码:

  • 具有纯粹的引用计数 GC,
  • 让您返回到堆栈中多个帧的某个点(窃取 Common Lisp 的 (return-from) 表单),
  • 并允许您为每种数据类型定义一个析构函数(在数据结构的内存被释放之前立即调用)。

您将如何实施?你能用 C 的 setjmp()longjmp() 以及在展开堆栈时返回清理的全局点列表(很好)吗?

另一种可能性是只生成 C++ 代码。

【问题讨论】:

    标签: compiler-construction destructor


    【解决方案1】:

    我首先会考虑几种方法。

    一个类似于异常帧。创建每个线程的结构链表。在调用函数之前,在堆栈上创建一个结构并将其添加到列表的末尾。该结构包含jmp_buf。调用setjmp,如果它返回0,则继续使用此函数,否则(以某种方式)检查您是否是return-from 的目标——如果是,则继续使用该函数,否则清理您的本地人和longjmp上一帧。我认为这可能有点矫枉过正,这取决于return-from 需要有多灵活。是否只需要从周围词法范围内的函数返回,或者我们实际上是否在调用堆栈中搜索可能存在或什至可能不存在的命名函数?如果是前者,我怀疑我们是否需要这个。

    另一种可能性是让所有引用计数类型实现一个公共接口(在语言实现内部,这是 - 它不需要对用户可见)。然后,您可以创建一个需要清理的(指向)对象的堆栈,以及在该堆栈中创建对应于调用堆栈级别的索引点的能力。在函数退出时,您可以清除要返回的堆栈级别以下的所有变量,只需通过循环遍历列表来取消每个变量,而不需要跳转到调用堆栈上我们上面的例程中的清理代码段。然后你可以longjmp 直接到目标,或者你可以提出一个“调用约定”,其中就你的语言而言,返回值实际上存储在由指针参数确定的位置(out-param ),而就 C 而言,返回值指示您要返回到堆栈的哪个位置。调用者因此检查返回值是否与自己的级别匹配,如果不立即返回,则不需要longjmplongjmp 可能会也可能不会更有效,这取决于您跳过了多少堆栈级别,因此检查并返回的重复次数。

    这个方案有点像 Symbian/C++ 中的清理堆栈。事实上,这更进一步 - 不是要清理的资源必须实现公共接口,堆栈上发生的是一个 TCleanupItem ,它由一个知道如何释放资源的函数和一些数据提供给那个函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-03
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 2016-07-01
      • 2011-04-06
      相关资源
      最近更新 更多