Bison - 符号 table - 为 malloc 免费匹配

Bison - symbol table - matching free for malloc

我正在查看 Bison 手册中的 mfcalc 示例,我对符号 table 有疑问。

特别是在例程 putsym() 中,我们调用了 malloc,但我没有看到对 free 的相应调用。我们需要手动取消分配符号 table(以下代码中的 sym_table)还是该工具会自动处理这个问题?

symrec *
putsym (char const *sym_name, int sym_type)
{
  symrec *ptr = (symrec *) malloc (sizeof (symrec));
  ptr->name = (char *) malloc (strlen (sym_name) + 1);
  strcpy (ptr->name,sym_name);
  ptr->type = sym_type;
  ptr->value.var = 0; /* Set value to 0 even if fctn.  */
  ptr->next = (struct symrec *)sym_table;
  sym_table = ptr;
  return ptr;
}

"The tool" 对你的行为一无所知。

我引用 "the tool" 因为在现实中,大多数解析项目至少涉及两个代码生成工具:解析器生成器(在本例中为 bison)和扫描器生成器((f)lex,也许)。 mfcalc 示例使用手工构建的词法分析器来避免依赖于 lex,尽管使用 (f)lex 可能更简单。无论如何,对符号 table 库的唯一调用是在扫描器中,与 bison 生成的代码完全无关。

当然,还有其他工具在起作用。例如,整个项目是用 C 编译器构建的,并在某种托管环境中运行(使用 C 标准的话);换句话说,一个操作系统和运行时支持库,其中包括 mallocfree 的实现(尽管正如您指出的那样,示例代码无处调用 free)。

最后提到这些是因为它们与您的问题相关。当一个进程终止时,所有进程资源都被释放,包括它的内存映像。 (这不是 C 标准所要求的,但几乎所有托管环境都是这样工作的。)因此,如果内存将被使用到程序终止,您实际上不需要 free() 分配内存。

与全局变量一样,未释放的内存分配曾经非常普遍。如今,这些事情被认为是不好的做法(充其量),大多数程序员都会避免它们,但情况并非总是如此。曾经有一段时间,许多程序员认为跟踪资源只是为了在程序终止前释放它们,或者跳过必要的环节以确保终止前清理保证执行是一种浪费。 (即使在今天,许多程序员只会在发生不可恢复的错误时插入对 exit(1) 的调用,而不是去追踪并手动释放每个分配的内存块。特别是在非生产代码中。)

无论您是否赞成这种编码风格,野牛手册中的示例(以及许多其他各种代码示例)都可以追溯到那个纯真的时代。

因此,此示例中的符号 table 条目确实从未被释放。您的生产代码可能应该做得更好,但它也可能应该使用更高效的数据结构并避免依赖于(单个)全局上下文。但是 none 与 mfcalc 试图说明的野牛特征有关。