LEX扫描器处理超长嵌套注释时输入缓冲区溢出问题排查与解决
问题:Flex扫描超长嵌套注释时出现缓冲区溢出错误
我定义了一个用于扫描嵌套注释的LEX扫描器,规则如下:
"(*" { int linenoStart, level, ch; linenoStart = yylineno; level = 1; do { ch = input(); switch (ch) { case '(': ch = input(); if (ch == '*') { level++; } else { unput(ch); } break; case '*': ch = input(); if (ch == ')') { level--; } else { unput(ch); } break; case '\n': yylineno++; break; } } while ((level > 0) && (ch > 0)); assert((ch >= 0) || (ch == EOF)); if (level > 0) { fprintf(stderr, "error: unterminated comment starting at line %d", linenoStart); exit(EXIT_FAILURE); } }
使用FLEX 2.6.4编译后,当扫描包含超过16382字符的注释的输入文件时,出现错误提示:
input buffer overflow, can't enlarge buffer because scanner uses REJECT
错误原因
- 默认缓冲区大小限制:Flex默认输入缓冲区大小为16384字节(16KB),当注释内容长度接近或超过这个阈值时,会触发缓冲区溢出。
unput()导致扩容禁用:你的扫描器中使用了unput()函数,Flex的实现逻辑中,一旦扫描器调用unput()或REJECT,会自动禁用缓冲区自动扩容功能——这些操作依赖缓冲区的固定内存位置,扩容会破坏已存入缓冲区的回退字符状态,因此Flex拒绝扩容并抛出错误。
解决方法
方法一:手动增大缓冲区大小
在Flex源码开头添加缓冲区配置选项,直接设置更大的缓冲区(比如64KB),避免小缓冲区不足以容纳超长注释:
%option 8bit %option buffer-size=65536 // 根据实际需求调整大小,单位为字节
方法二:改用Flex状态机处理嵌套注释(推荐)
放弃手动调用input()和unput()的方式,利用Flex内置状态管理和模式匹配处理嵌套注释,这种方式符合Flex设计风格,且不会触发缓冲区扩容限制:
%option 8bit %option yylineno // 启用行号统计 %x COMMENT // 定义注释状态 %% // 进入嵌套注释 "(*" { BEGIN(COMMENT); int comment_level = 1; } // 注释内遇到新的嵌套注释,层级加1 <COMMENT>"(*" { comment_level++; } // 注释内遇到结束标记,层级减1;层级为0时回到初始状态 <COMMENT>"*)" { if (--comment_level == 0) BEGIN(INITIAL); } // 注释内换行,更新行号 <COMMENT>\n { yylineno++; } // 忽略注释内的其他所有字符 <COMMENT>. { /* do nothing */ } // 注释未结束就遇到EOF,抛出错误 <COMMENT><<EOF>> { fprintf(stderr, "error: unterminated comment starting at line %d", yylineno); exit(EXIT_FAILURE); }
内容的提问来源于stack exchange,提问作者August Karlstrom
相关产品推荐
相关产品推荐

