输入字符串长度超9时AST创建触发段错误求助
问题分析与解决
问题原因
- Flex正则规则语法错误:你的范围匹配规则写错了——把匹配左方括号的
\[误写成了\^(匹配脱字符^)。原规则\[^?([^\\\]]|\\.)*\]实际会匹配以^开头、后跟可选?、最后以]结尾的字符串,完全不符合你要解析的[...]格式范围表达式。 - 错误匹配引发内存越界:由于规则不匹配预期输入,Flex要么触发其他规则处理(逻辑不符),要么在错误匹配逻辑下导致
yytext指向的缓冲区出现越界访问,最终在创建AST时触发段错误。 - 补充:你用
strdup(yytext)的操作是正确的(避免Flex内部缓冲区覆盖问题),但规则错误导致yytext内容异常,才引发后续问题。
解决步骤
1. 修正Flex正则规则
将规则中的\^改为\[,正确匹配左方括号,同时保留可选的脱字符(用于否定范围,如[^abc])。修正后的规则:
\[\^?([^\\\]]|\\.)*\] { yylval.value = strdup(yytext); return TOKEN_RANGE; }
规则拆解:
\[:匹配左方括号[\^?:可选匹配脱字符^(支持[^123]这类否定范围)([^\\\]]|\\.)*:匹配任意非]且非转义开头的字符,或转义后的任意字符(支持\[这类转义括号)\]:匹配右方括号]
2. 添加未匹配输入的错误处理
在Flex规则末尾添加默认规则,捕获未匹配的字符,避免Flex默认输出未匹配内容导致的意外行为:
. { fprintf(stderr, "Unexpected character: %c\n", yytext[0]); exit(1); }
3. 强化AST创建的鲁棒性
在CreateAstLeaf中添加长度检查,避免空字符串或异常长度输入导致的问题:
ast_t *CreateAstLeaf(node_t type, char *val) { ast_t *new_leaf = malloc(sizeof(ast_t)); if (!new_leaf) { perror("Out of space."); exit(1); } if (val == NULL || strlen(val) == 0) { fprintf(stderr, "Invalid empty range string.\n"); exit(1); } new_leaf->type = type; size_t val_len = strlen(val); new_leaf->value = calloc(val_len + 1, sizeof(char)); strcpy(new_leaf->value, val); return new_leaf; }
4. 调试匹配过程
可以在Flex规则中添加打印语句,确认匹配内容是否符合预期:
\[\^?([^\\\]]|\\.)*\] { printf("Matched range token: %s\n", yytext); yylval.value = strdup(yytext); return TOKEN_RANGE; }
验证测试
修正后重新编译Flex和Bison代码,测试长范围输入:
./parse -r /[1234567890abcdef]/
此时应该正常输出Accepted!,不再触发段错误。
内容的提问来源于stack exchange,提问作者Karidus
相关产品推荐
相关产品推荐

