基于Yacc-Lex的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

