Bison如何正确使用字符串返回值 解决返回字符串包含多余字符问题
Bison字符串返回值使用及多余字符问题解决方案
核心问题根因
你遇到的字符串包含多余字符、解析错误的问题,本质是以下3个底层错误导致:
- 直接引用Flex的
yytext缓冲区:yytext是Flex内部的复用缓冲区,每次识别新token时内容会被覆盖,直接将yytext指针赋值给语义值会导致后续token解析时原有内容被篡改,出现随机字符、多余符号。 - token规则附带多余空白符:你定义的
WORD、MULTIWORD等规则末尾均添加了{WHITE_SPACE}*,会导致识别到的token本身就包含末尾的空格,甚至可能因为规则优先级问题误将后续符号(如})包含到token内容中。 - 非法内存释放操作:未经过
malloc的yytext指针直接调用free会触发内存访问错误,进一步导致内容异常。
正确使用方式及修复步骤
1. 改造Flex词法规则,复制token内容到独立内存
所有返回字符串类型的token,都需要将yytext的内容复制到新申请的堆内存中,使用Flex内置的yyleng变量获取当前token的实际长度,示例如下:
// WORD 类型token处理示例 {WORD} { yylval.string = malloc(yyleng + 1); strncpy(yylval.string, yytext, yyleng); yylval.string[yyleng] = '\0'; // 手动补字符串结束符 return WORD; } // 带前缀的ATWORD处理示例(跳过第一个@字符) {ATWORD} { yylval.string = malloc(yyleng); // 跳过1个前缀字符,总长度为 yyleng-1 + 1个结束符 = yyleng strncpy(yylval.string, yytext + 1, yyleng - 1); yylval.string[yyleng - 1] = '\0'; return ATWORD; }
HWORD、UNIT、MULTIWORD等所有返回字符串类型的token都按照上述逻辑修改。
2. 移除规则末尾的多余空白符匹配
你已经单独配置了[ \t]规则忽略空白符,无需在每个token规则末尾添加{WHITE_SPACE}*,直接删除所有token规则末尾的{WHITE_SPACE}*即可,避免token包含多余空格。
3. 修正Bison规则中的字符串操作
- 单值返回场景:第一条
timer规则直接写$$ = $2即可,只要$2是你独立申请的字符串内存,就能正常返回amount的值,无需额外处理。 - 多字符串拼接场景:按需申请内存,使用
snprintf避免溢出,示例如下:
| TILDE WORD amount { printf("Timer: %s Amount:%s\n",$2, $3 ); // 申请内存长度= $2长度 + $3长度 + 1个空格 + 1个结束符 $$ = malloc(strlen($2) + strlen($3) + 2); snprintf($$, strlen($2) + strlen($3) + 2, "%s %s", $2, $3); free($2); free($3); }
所有字符串使用完成后,再调用free释放内存即可,不会出现非法释放问题。
内容的提问来源于stack exchange,提问作者Seth Harlaar
相关产品推荐
相关产品推荐

