Lex与Yacc间指针传递异常求助:VAR类型指针传递失败
Lex/Yacc中变量名指针传递异常的问题
我在.l文件中使用正则表达式匹配变量名,将该名称传入函数获取指针后返回,但该指针在Lex与Yacc的传递过程中发生了莫名改变;而检测字符串时执行相同操作却未出现此问题。
代码示例如下:
\"([^\"]+)\" yylval = removeQuotes(yytext); return STRING; [a-z_][a-z0-9_]* yylval = returnVar(yytext); return VAR; %% long removeQuotes(char* str) { int i; for (i=1; str[i]!='\0'; i++){ str[i-1] = str[i]; } str[i-2] = '\0'; return (long)str; } long returnVar(char* name){ return (long)name; }
STRING类型可正常在程序中使用,但VAR类型指针无法正确传递到Yacc,导致无法获取对应的变量名字符串。示例:returnVar返回指针39035008,Yacc中显示为39051408。请问为何指针未按预期传递?removeQuotes中修改输入的操作是否对此有影响?
问题原因分析
- yytext的生命周期限制:Lex的
yytext是内部维护的临时缓冲区,每次词法分析完成(即returntoken之后),这个缓冲区会被Lex重用或覆盖。VAR类型直接返回yytext的指针,当Lex继续解析后续token时,yytext指向的内存内容已经被修改,Yacc拿到的自然不是原本的变量名指针。 - STRING类型的“假正常”:你在
removeQuotes中直接修改了yytext的内容,返回的仍是yytext指针。这种做法本质上同样不安全,只是测试场景中STRING之后没有触发缓冲区覆盖,才看似正常。一旦后续有其他词法解析操作,STRING的指针也会失效。
解决方案
核心思路是为需要传递的字符串分配独立内存,彻底脱离Lex临时缓冲区的限制:
- 修改
returnVar函数,用strdup复制变量名到新内存:
long returnVar(char* name){ // strdup自动分配内存并复制字符串,返回新内存指针 return (long)strdup(name); }
- 修改
removeQuotes函数,不再直接修改yytext,而是分配新内存处理去引号逻辑:
long removeQuotes(char* str) { int new_len = strlen(str) - 2; char* new_str = malloc(new_len + 1); if (!new_str) { // 处理内存分配失败情况 fprintf(stderr, "Memory allocation failed\n"); exit(1); } // 复制引号内的内容到新内存 strncpy(new_str, str + 1, new_len); new_str[new_len] = '\0'; return (long)new_str; }
- 内存释放注意:Yacc处理完这些字符串后,记得调用
free释放分配的内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Lee
相关产品推荐
相关产品推荐

