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

使用Lex和Yacc解析Shell输入时捕获命令字符串值遇段错误求助

解决Lex/Yacc解析Shell管道命令时的段错误问题

我之前刚用Lex/Yacc写类似解析器的时候也踩过这个坑!你的代码里有两个关键问题导致了段错误,咱们一步步来解决:

核心问题:Lex不知道yylval的类型

你在Yacc里定义了YYSTYPE为char*,但Lex默认会把yylval当成int类型处理。当你用strdup(yytext)把字符串指针赋值给yylval时,64位系统下指针是8字节,会被截断成int的4字节,传到Yacc里的$1就变成了无效的垃圾地址,打印时自然触发段错误。

修改步骤

1. 修复Lex文件的类型声明

在Lex的%{ ... %}块里,添加extern YYSTYPE yylval;,确保Lex知道yylval是字符串指针类型。另外还要补充空白字符的忽略规则,避免输入空格换行时触发错误:

%{
#include <stdio.h>
#include "y.tab.h"
#include <string.h>
// 显式声明yylval的类型,让Lex正确处理指针
extern YYSTYPE yylval;
%}

%%
(grep|vim|ls|who) {
    yylval = strdup(yytext);
    return COMMAND;
}
"|" return PIPE;
[ \t\n]+ ; // 忽略空格、制表符和换行
. { yyerror("invalid character"); } // 处理非法字符
%%

2. 补充内存释放(可选但推荐)

strdup会在堆上分配内存,用完后记得释放避免内存泄漏,修改Yacc里的command规则:

%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // 要包含stdlib.h才能用free
#define YYSTYPE char*
void yyerror(const char* str) { fprintf(stderr, "error: %s\n", str); }
int yywrap() { return 1; }
main() { yyparse(); }
%}

%token PIPE COMMAND

%%
statement: command 
         | statement PIPE command 
         ;
command: COMMAND { 
    printf("command: %s encountered\n", $1); 
    free($1); // 释放strdup分配的内存
} ;
%%

编译运行顺序

别忘按正确顺序编译:

yacc -d parser.y
flex scanner.l
gcc y.tab.c lex.yy.c -o shell_parser
./shell_parser

现在输入ls | grep test,就能正常打印命令,不会再出现段错误啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:33:12