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

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是内部维护的临时缓冲区,每次词法分析完成(即return token之后),这个缓冲区会被Lex重用或覆盖。VAR类型直接返回yytext的指针,当Lex继续解析后续token时,yytext指向的内存内容已经被修改,Yacc拿到的自然不是原本的变量名指针。
  • STRING类型的“假正常”:你在removeQuotes中直接修改了yytext的内容,返回的仍是yytext指针。这种做法本质上同样不安全,只是测试场景中STRING之后没有触发缓冲区覆盖,才看似正常。一旦后续有其他词法解析操作,STRING的指针也会失效。

解决方案

核心思路是为需要传递的字符串分配独立内存,彻底脱离Lex临时缓冲区的限制:

  1. 修改returnVar函数,用strdup复制变量名到新内存:
long returnVar(char* name){
    // strdup自动分配内存并复制字符串,返回新内存指针
    return (long)strdup(name);
}
  1. 修改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;
}
  1. 内存释放注意:Yacc处理完这些字符串后,记得调用free释放分配的内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:32:51