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 标准的话);换句话说,一个操作系统和运行时支持库,其中包括 malloc
和 free
的实现(尽管正如您指出的那样,示例代码无处调用 free
)。
最后提到这些是因为它们与您的问题相关。当一个进程终止时,所有进程资源都被释放,包括它的内存映像。 (这不是 C 标准所要求的,但几乎所有托管环境都是这样工作的。)因此,如果内存将被使用到程序终止,您实际上不需要 free()
分配内存。
与全局变量一样,未释放的内存分配曾经非常普遍。如今,这些事情被认为是不好的做法(充其量),大多数程序员都会避免它们,但情况并非总是如此。曾经有一段时间,许多程序员认为跟踪资源只是为了在程序终止前释放它们,或者跳过必要的环节以确保终止前清理保证执行是一种浪费。 (即使在今天,许多程序员只会在发生不可恢复的错误时插入对 exit(1)
的调用,而不是去追踪并手动释放每个分配的内存块。特别是在非生产代码中。)
无论您是否赞成这种编码风格,野牛手册中的示例(以及许多其他各种代码示例)都可以追溯到那个纯真的时代。
因此,此示例中的符号 table 条目确实从未被释放。您的生产代码可能应该做得更好,但它也可能应该使用更高效的数据结构并避免依赖于(单个)全局上下文。但是 none 与 mfcalc
试图说明的野牛特征有关。
我正在查看 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 标准的话);换句话说,一个操作系统和运行时支持库,其中包括 malloc
和 free
的实现(尽管正如您指出的那样,示例代码无处调用 free
)。
最后提到这些是因为它们与您的问题相关。当一个进程终止时,所有进程资源都被释放,包括它的内存映像。 (这不是 C 标准所要求的,但几乎所有托管环境都是这样工作的。)因此,如果内存将被使用到程序终止,您实际上不需要 free()
分配内存。
与全局变量一样,未释放的内存分配曾经非常普遍。如今,这些事情被认为是不好的做法(充其量),大多数程序员都会避免它们,但情况并非总是如此。曾经有一段时间,许多程序员认为跟踪资源只是为了在程序终止前释放它们,或者跳过必要的环节以确保终止前清理保证执行是一种浪费。 (即使在今天,许多程序员只会在发生不可恢复的错误时插入对 exit(1)
的调用,而不是去追踪并手动释放每个分配的内存块。特别是在非生产代码中。)
无论您是否赞成这种编码风格,野牛手册中的示例(以及许多其他各种代码示例)都可以追溯到那个纯真的时代。
因此,此示例中的符号 table 条目确实从未被释放。您的生产代码可能应该做得更好,但它也可能应该使用更高效的数据结构并避免依赖于(单个)全局上下文。但是 none 与 mfcalc
试图说明的野牛特征有关。