Flex yy_scan_string 内存泄漏

Flex yy_scan_string memory leaks

描述

创建此示例是为了从更大的解决方案中引入问题。我必须使用 flex 和 yy_scan_string()。我在 flex 中遇到内存泄漏问题(下面的代码)。在此示例中,内存泄漏被标记为 "still reachable",但在原始解决方案中,它们被标记为 "lost memory".

我认为这个问题是在 flex 内部分配的内存中的某个地方,我不知道如何正确释放它,我找不到关于该问题的任何教程/文档。

file.lex

%option noyywrap                   

%{                    
#include <stdio.h>
%}

%%
. printf("%s\n", yytext);
%%

int main() {
    printf("Start\n");
    yy_scan_string("ABC");
    yylex();
    printf("Stop\n");
    return 0;
}
bash$ flex file.lex
bash$ gcc lex.yy.c
bash$ ./a.out
Start
H
a
l
l
o

W
o
r
l
d
Stop
bash$ valgrind --leak-check=full --show-leak-kinds=all ./a.out
==6351== Memcheck, a memory error detector
==6351== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6351== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==6351== Command: ./a.out
==6351==
==6351== error calling PR_SET_PTRACER, vgdb might block
Start
A
B
C
Stop
==6351==
==6351== HEAP SUMMARY:
==6351==     in use at exit: 77 bytes in 3 blocks
==6351==   total heap usage: 4 allocs, 1 frees, 589 bytes allocated
==6351==
==6351== 5 bytes in 1 blocks are still reachable in loss record 1 of 3
==6351==    at 0x483577F: malloc (vg_replace_malloc.c:299)
==6351==    by 0x10AE84: yyalloc (in ./a.out)
==6351==    by 0x10ABE5: yy_scan_bytes (in ./a.out)
==6351==    by 0x10ABBC: yy_scan_string (in ./a.out)
==6351==    by 0x10AEE2: main (in /home/./a.out)
==6351==
==6351== 8 bytes in 1 blocks are still reachable in loss record 2 of 3
==6351==    at 0x483577F: malloc (vg_replace_malloc.c:299)
==6351==    by 0x10AE84: yyalloc (in ./a.out)
==6351==    by 0x10A991: yyensure_buffer_stack (in ./a.out)
==6351==    by 0x10A38D: yy_switch_to_buffer (in ./a.out)
==6351==    by 0x10AB8E: yy_scan_buffer (in ./a.out)
==6351==    by 0x10AC68: yy_scan_bytes (in ./a.out)
==6351==    by 0x10ABBC: yy_scan_string (in ./a.out)
==6351==    by 0x10AEE2: main (in ./a.out)
==6351==
==6351== 64 bytes in 1 blocks are still reachable in loss record 3 of 3
==6351==    at 0x483577F: malloc (vg_replace_malloc.c:299)
==6351==    by 0x10AE84: yyalloc (in ./a.out)
==6351==    by 0x10AAEF: yy_scan_buffer (in ./a.out)
==6351==    by 0x10AC68: yy_scan_bytes (in ./a.out)
==6351==    by 0x10ABBC: yy_scan_string (in ./a.out)
==6351==    by 0x10AEE2: main (in ./a.out)
==6351==
==6351== LEAK SUMMARY:
==6351==    definitely lost: 0 bytes in 0 blocks
==6351==    indirectly lost: 0 bytes in 0 blocks
==6351==      possibly lost: 0 bytes in 0 blocks
==6351==    still reachable: 77 bytes in 3 blocks
==6351==         suppressed: 0 bytes in 0 blocks
==6351==
==6351== For counts of detected and suppressed errors, rerun with: -v
==6351== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

答案在flex文档中有提到,但是你得仔细阅读才能找到。 (见下文。)

如果生成可重入扫描器,则您负责创建和销毁所需的每个扫描器对象,并且扫描器对象管理扫描器实例所需的所有内存。但是即使不使用可重入接口,也可以使用yylex_destroy来管理内存。在传统的不可重入接口中,则没有scanner_t参数,所以yylex_destroy的原型就是

int yylex_destroy(void);

(虽然它有一个 return 应该是状态代码的值,但它永远不会 return 出错。)

如果你愿意,你可以调用yylex_init,它在非可重入接口中也没有参数,但与可重入接口不同,没有必要调用它。

来自 memory management 上的手册章节:

Flex allocates dynamic memory during initialization, and once in a while from within a call to yylex(). Initialization takes place during the first call to yylex(). Thereafter, flex may reallocate more memory if it needs to enlarge a buffer. As of version 2.5.9 Flex will clean up all memory when you call yylex_destroy See faq-memory-leak.


示例:

$ cat clean.l
%option noinput nounput noyywrap nodefault
%{                    
#include <stdio.h>
%}

%%
.|\n ECHO;
%%

int main() {
    printf("Start\n");
    yy_scan_string("ABC");
    yylex();
    printf("Stop\n");
    yylex_destroy();
    return 0;
}

$ flex -o clean.c clean.l
$ gcc -Wall -o clean clean.c
$ valgrind --leak-check=full --show-leak-kinds=all ./clean
==16187== Memcheck, a memory error detector
==16187== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16187== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16187== Command: ./clean
==16187== 
Start
ABCStop
==16187== 
==16187== HEAP SUMMARY:
==16187==     in use at exit: 0 bytes in 0 blocks
==16187==   total heap usage: 4 allocs, 4 frees, 1,101 bytes allocated
==16187== 
==16187== All heap blocks were freed -- no leaks are possible
==16187== 
==16187== For counts of detected and suppressed errors, rerun with: -v
==16187== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)