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

基于Yacc-Lex的C编译器程序语法错误与段错误排查请求

语法树构建C程序的错误排查与修正建议

以下是针对你提供的代码中存在的问题及修正方案:

1. 函数声明与定义大小写不匹配

声明的函数为makenode,但定义时写成了makeNode,C语言区分大小写,这会直接导致编译/链接错误。
修正:将声明改为struct tnode* makeNode(char *c,int t,char d,struct tnode *l,struct tnode *m,struct tnode *r);,或把定义改为makenode保持名称一致。

2. makeNode函数未处理NULL参数

当传入的c为NULL时,strlen(c)会触发段错误,因为NULL不是有效的字符串指针。
修正:添加NULL检查逻辑:

struct tnode* makeNode(char *c, int t, char d, struct tnode *l, struct tnode *m, struct tnode *r){
    struct tnode *temp = (struct tnode*)malloc(sizeof(struct tnode));
    // 处理c为NULL的情况
    if (c != NULL) {
        temp->var = (char*)malloc(sizeof(char)*(strlen(c)+1));
        strcpy(temp->var, c);
    } else {
        temp->var = NULL;
    }
    // ... 其余原有代码
}

3. postfix函数混淆type与nodetype字段

注释明确nodetype=4代表数值/字符串常量,但代码中错误判断if(t->type == 4)——type字段存储的是字符类型标识(如'i'、'b'),整数4与字符'i'(ASCII码105)不相等,会导致逻辑错误,甚至访问NULL指针触发段错误。
修正:将条件改为基于nodetype判断:

void postfix(struct tnode *t)
{
    if(t->nodetype == 4)
    {  
        if(t->strng == NULL)
            printf("%d ",t->val);
        else
            printf("%s ",t->strng);
    }
    else if(t->nodetype == 5 || t->nodetype == 8 || t->nodetype == 9)
    {
        printf("%s ",t->var);
    }
    else{
        // ... 其余原有代码
    }
}

4. postfix函数未检查子节点是否为NULL

递归调用postfix前未判断left、mid、right是否为NULL,若子节点为NULL会直接触发段错误。
修正:添加NULL检查:

else{
    if (t->left != NULL) postfix(t->left);
    if (t->nodetype == 6 && t->mid != NULL) postfix(t->mid);
    if ((t->nodetype == 3 || t->nodetype == 2 || t->nodetype == 6 || t->nodetype == 7) && t->right != NULL) postfix(t->right);
    printf("%s ",t->var);    
}

5. view函数内存泄漏

函数中先malloc了temp,随后立刻将其赋值为head,导致malloc的内存无法释放,造成内存泄漏。
修正:直接定义指针指向head,无需malloc:

void view()
{ 
    printf("Name\t Type\t Size\t Binding\n");
    struct Gsymbol* temp = head;
    while(temp!=NULL)
    { 
        printf("%s\t %d\t %d\t %d\n", temp->name, temp->type, temp->size, temp->binding);
        temp = temp->next;
    }
}

6. install函数错误使用perror

perror用于输出系统调用的错误信息,会自动附加errno对应的描述,但此处是用户自定义的变量重定义错误,使用perror会导致错误信息不准确(比如附加无关的"Success")。
修正:改用fprintf输出到标准错误流:

if(lookup(na) != NULL)
{
    char er[100] = "Variable re-initialized: ";
    strcat(er, na);
    fprintf(stderr, "%s\n", er);
    exit(1);
}

7. makeLeafNode和makevarnode硬编码type字段

两个函数中temp->type固定为'i',但字符串常量、布尔变量等场景需要对应不同类型,硬编码会导致后续类型检查失效。
修正:添加参数传递类型,例如修改makeLeafNode:

struct tnode* makeLeafNode(char* c, int n, char type)
{
    struct tnode *temp = (struct tnode*)malloc(sizeof(struct tnode));
    // ... 原有代码
    temp->type = type;
    // ... 其余代码
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:24:59