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

C+YACC中变量被覆盖的原因是什么?

为什么C+YACC中的变量会被覆盖?

嘿,我来帮你排查下这个变量覆盖的问题,结合你贴的代码片段,大概率是这几个常见的坑导致的:

1. 字符串缓冲区复用搞的鬼

如果你的词法分析器(Flex/LEX)里用了静态字符数组来存标识符或者数值字符串,比如像下面这样:

// 假设LEX里的代码
static char buf[256];
// 匹配到数值或字符串时
strcpy(buf, yytext);
yylval.e.value = buf;

那麻烦就来了——所有赋值操作里的value都会指向同一个buf缓冲区。每次新的赋值都会把buf里的内容覆盖掉,结果就是你存在variables数组里的所有指针,全指向这块不断被改写的内存,看起来就像旧变量的值被新变量覆盖了。

解决办法很简单:给每个变量的字符串值单独分配内存,用strdup最省事(它会自动malloc内存并复制字符串),或者手动malloc+strcpy也行:

// 在action函数处理ASSIGN动作时
int idx = tolower(id) - 'a'; // 先转成小写确保索引正确
variables[idx] = strdup(value);
// 或者手动来
size_t val_len = strlen(value);
variables[idx] = malloc(val_len + 1);
if (variables[idx] != NULL) {
    strcpy(variables[idx], value);
}

别忘了程序结束时遍历variables数组,用free把内存释放掉,不然会漏内存。

2. 临时栈变量的坑

如果在语义动作里,你把栈上的临时变量地址直接传给了action函数,比如:

// 某个YACC语义动作里
char temp_buf[256];
sprintf(temp_buf, "%d", some_int_value);
action(ASSIGN, 'x', temp_buf);

等这个语义动作执行完,栈上的temp_buf就被销毁了,variables['x'-'a']就变成了悬空指针。后面其他函数调用的栈操作很可能会覆盖这块内存,结果就是变量值莫名其妙被篡改。

同样,解决思路还是给值分配独立的堆内存,别用栈上的临时变量当持久化的指针。

3. 标识符索引算错了

你的variables是大小26的数组,对应26个字母,但如果处理标识符时没统一大小写,或者索引计算错了,比如:

// 错误示例:直接用字符ASCII码当索引
variables[id] = value; // 比如id是'x',ASCII是120,直接越界访问数组

这种越界操作会乱改数组外面的内存,可能无意中覆盖其他变量的指针,或者used_ids数组的内容,表现出来就是变量值被覆盖。

一定要把标识符转成正确的0-25索引,比如统一转小写后减'a':

int idx = tolower(id) - 'a';
if (idx < 0 || idx >= 26) {
    yyerror("Invalid variable name - only a-z allowed");
    return 1;
}
// 再操作variables[idx]

4. 表达式结构体的内存复用问题

你的%union里定义了struct expression,如果这个结构体里的value指针被多个表达式节点复用,或者没给每个表达式的value分配独立内存,也会导致后续操作覆盖之前的变量值。比如多个表达式共享同一个value指针,改一个就全变了。

建议在生成表达式节点的时候,确保每个value都是单独分配的内存,别指向同一个临时缓冲区。


你可以先检查LEX里的缓冲区使用方式,还有action函数里赋值时的内存处理,这俩地方是变量覆盖问题的重灾区。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:54:40