You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flex在Action中处理EOF遇异常:无限输出/段错误求解决

环境
  • OS: MacOS Monterey 12.6(搭载Apple M1 Pro)
  • 版本: flex 2.6.4 Apple(flex-34)
问题

我编写了以下Flex代码,想要在Action中自行处理EOF,用于测试文件末尾存在unclosed comment(未闭合注释)的场景:

%{
#include <stdio.h>
int yywrap(void) {
    return 1;
}
%}

ID  [a-z][a-zA-Z0-9]*
DIGIT [0-9]

%%

{DIGIT}+    {printf("num");}

{ID}    printf("id: %s\n", yytext);

"/*"    {
    int c;

    for ( ; ; ) {
        while ( (c = input()) != '*' && c != EOF )
            printf("%x\n", c);

        if ( c == '*' ) {
            while ( (c = input()) == '*' )
                printf("%x\n", c);
            if ( c == '/' )
                break;    /* found the end */
            }

        if ( c == EOF ) {
            printf( "EOF in comment" );
            break;
        }
    }
}
%%

int main(int argc, char **argv) {
    ++argv, --argc;
    if (argc > 0) {
        yyin = fopen(argv[0], "r");
    } else {
        yyin = stdin;
    }
    yylex();
    return 0;
}

测试用的注释文件内容:

/* **jfiowejfiowe
 *
 *

执行编译命令:

lex test.lex
gcc lex.yy.c -o lextest
./lextest comment.c

程序出现无限输出0的异常。我尝试修改yywrap()返回0,运行后触发segmentation fault;改用yyterminate()的写法,依然出现段错误。

问题分析与解决

1. 异常原因拆解

  • 无限输出0:原代码缺少默认匹配规则,Flex会将未匹配的字符直接输出到标准输出;同时注释处理逻辑中,EOF的判断分支可能因循环逻辑疏漏,导致重复触发输出操作。另外,未正确使用换行符\n可能引发输出缓冲异常,看起来像是无限输出。
  • Segmentation Fault:yywrap()返回0的语义是告知Flex还有后续输入文件需要处理,但你并未设置新的yyin文件指针,Flex会尝试读取空指针,直接触发段错误。用yyterminate()的写法本质是返回0,和上述情况一致,同样会导致错误。

2. 修正后的代码

%{
#include <stdio.h>
int yywrap(void) {
    return 1; // 返回1表示无后续输入,是正常终止的正确写法
}
%}

ID  [a-z][a-zA-Z0-9]*
DIGIT [0-9]

%%

{DIGIT}+    {printf("num\n");}

{ID}        {printf("id: %s\n", yytext);}

"/*"        {
    int c;
    while (1) {
        // 读取直到'*'或EOF
        while ((c = input()) != '*' && c != EOF) {
            printf("%x\n", c);
        }
        if (c == EOF) {
            printf("EOF in comment\n");
            break;
        }
        // 读取连续的'*'
        do {
            printf("%x\n", c);
            c = input();
        } while (c == '*');
        if (c == '/') {
            // 找到注释结束符,退出循环
            break;
        } else if (c == EOF) {
            printf("EOF in comment\n");
            break;
        }
    }
}

.           { /* 忽略未匹配的单个字符,避免Flex默认输出 */ }

%%

int main(int argc, char **argv) {
    ++argv;
    --argc;
    if (argc > 0) {
        yyin = fopen(argv[0], "r");
        if (!yyin) { // 添加文件打开失败的错误处理
            perror("fopen failed");
            return 1;
        }
    } else {
        yyin = stdin;
    }
    yylex();
    if (yyin != stdin) {
        fclose(yyin); // 关闭打开的文件,避免资源泄漏
    }
    return 0;
}

3. 关键修正点

  • 保留yywrap()返回1的写法,符合无后续输入的场景语义;
  • 优化注释处理的循环逻辑,确保EOF触发后能直接退出循环;
  • 添加默认规则.忽略未匹配字符,避免Flex自动输出无关内容;
  • 增加文件打开失败判断和文件关闭操作,完善错误处理与资源管理;
  • 统一printf使用\n换行,避免输出缓冲异常。

编译运行修正后的代码,测试未闭合注释场景时,会正确打印EOF in comment,且无无限输出或段错误问题。

内容的提问来源于stack exchange,提问作者hstk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:15:39