最少的野牛/flex生成的代码有内存泄漏 [英] Minimal bison/flex-generated code has memory leak
问题描述
在调试大型项目中的内存泄漏时,我发现泄漏的来源似乎是一些由flex/bison生成的代码.我能够使用以下由两个文件sand.l
和sand.y
组成的最小示例来重新创建泄漏:
In debugging a memory leak on a large project, I found that the source of the leak seemed to be some flex/bison-generated code. I was able to recreate the leak with the following minimal example consisting of two files, sand.l
and sand.y
:
在sand.l
中:
%{
#include <stdlib.h>
#include "sand.tab.h"
%}
%%
[0-9]+ { return INT; }
. ;
%%
sand.y
中:
%{
#include <stdio.h>
#include <stdlib.h>
int yylex();
int yyparse();
FILE* yyin;
void yyerror(const char* s);
%}
%token INT
%%
program:
program INT { puts("Found integer"); }
|
;
%%
int main(int argc, char* argv[]) {
yyin = stdin;
do {
yyparse();
} while (!feof(yyin));
return 0;
}
void yyerror(const char* s) {
puts(s);
}
代码是用
$ bison -d sand.y
$ flex sand.l
$ gcc -g lex.yy.c sand.tab.c -o main -lfl
使用valgrind运行程序会出现以下错误:
Running the program with valgrind gave the following error:
8 bytes in 1 blocks are still reachable in loss record 1 of 3
at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
by 0x40260F: yyalloc (lex.yy.c:1723)
by 0x402126: yyensure_buffer_stack (lex.yy.c:1423)
by 0x400B89: yylex (lex.yy.c:669)
by 0x402975: yyparse (sand.tab.c:1114)
by 0x402EC4: main (sand.y:24)
64 bytes in 1 blocks are still reachable in loss record 2 of 3
at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
by 0x40260F: yyalloc (lex.yy.c:1723)
by 0x401CBF: yy_create_buffer (lex.yy.c:1258)
by 0x400BB3: yylex (lex.yy.c:671)
by 0x402975: yyparse (sand.tab.c:1114)
by 0x402EC4: main (sand.y:24)
16,386 bytes in 1 blocks are still reachable in loss record 3 of 3
at 0x4C2AC3D: malloc (vg_replace_malloc.c:299)
by 0x40260F: yyalloc (lex.yy.c:1723)
by 0x401CF6: yy_create_buffer (lex.yy.c:1267)
by 0x400BB3: yylex (lex.yy.c:671)
by 0x402975: yyparse (sand.tab.c:1114)
by 0x402EC4: main (sand.y:24)
似乎野牛和/或flex保留了大量的记忆.反正有强迫他们释放的吗?
It seems that bison and/or flex is holding on to a substantial amount of memory. Is there anyway to force them to free it?
推荐答案
默认的flex框架会分配一个输入缓冲区和一个小的缓冲区堆栈,它们永远不会释放.您可以使用
The default flex skeleton allocates an input buffer and a small buffer stack, which it never frees. You could free the input buffer manually with yy_delete_buffer(YY_CURRENT_BUFFER);
but there is no way to delete the buffer stack. (It's only 8 bytes in your application, so it's not a disaster.)
如果要编写干净的应用程序,则应生成一个可重入扫描器,它将所有持久数据放入扫描仪上下文对象.您的代码必须分配并释放该对象,释放它将释放所有内存分配. (您可能还想生成一个纯解析器,其工作原理大致相同.)
If you want to write a clean application, you should generate a reentrant scanner, which puts all persistent data into a scanner context object. Your code must allocate and free this object, and freeing it will free all memory allocations. (You might also want to generate a pure parser, which works roughly the same way.)
但是,可重入扫描器具有非常不同的API,因此您将需要使解析器通过扫描器上下文对象.如果还使用可重入(纯)解析器,则需要修改扫描程序操作,因为对于可重入解析器,yylval
是YYSTYPE*
而不是YYSTYPE
.
However, the reentrant scanner has a very different API, so you will need to get your parser to pass through the scanner context object. If you use a reentrant (pure) parser as well, you'll need to modify your scanner actions because with the reentrant parser, yylval
is a YYSTYPE*
instead of YYSTYPE
.
这篇关于最少的野牛/flex生成的代码有内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!