C语言符号表Insert函数触发段错误(core dumped)问题求助
C语言符号表段错误问题解决
问题背景
需修改给定的C语言符号表代码,要求:
- 移除字符数组"label"
- 将结构体中的
symbol从char[]改为char* - 仅允许在
main函数中接收输入
修改后调用Insert函数时持续出现segmentation fault (core dumped)错误,调整链表赋值方式后问题依旧,原代码如下:
#include<stdio.h> /* #include<conio.h> */ #include<malloc.h> #include<string.h> #include<stdlib.h> int size=0; void Insert(); void Display(); void Delete(); // Prototypes declared since functions are declared after our main function. int Search(char lab[]); void Modify(); struct SymbTab { char* symbol; int addr; struct SymbTab *next;}; struct SymbTab *first,*last; //defines two pointers that are automatically set to NULL. void main() { // Main function: the only function that takes in input. int op,y; // Variable declarations. int addrs; char symbl[30]; do { printf("\n\tSYMBOL TABLE IMPLEMENTATION\n"); printf("\n\t1.INSERT\n\t2.DISPLAY\n\t3.DELETE\n\t4.SEARCH\n\t5.END\n"); printf("\n\tEnter your option : "); scanf("%d",&op); // Asks for input. switch(op) { // All possible responses to whatever the user inputs. case 1: // Calls the Insert case. printf("Insert symbol: "); fgets(symbl, sizeof(symbl), stdin); scanf("%s", symbl); // Takes user input and stores in symbol. printf("Insert address:"); scanf("%d", addrs); // Takes user input and stores in addr. Insert(symbl, addrs); // Passes symbol and addr (which now contain the user's input) as parameters into the Insert function. break; // Exists the Insert case and reruns starting at the beginning of the "do". case 2: // Calls the Display case. Display(); // Calls the Display function. break; // Exists the Display case and reruns starting at the beginning of the "do". case 3: // Calls the Delete case. printf("\n\tEnter the symbol to be deleted: %s", symbl); y = Search(symbl); if(y == 0) printf("\n\tLabel not found\n"); break; if (y == 1) Delete(symbl); break; // Exists the Delete case and reruns starting at the beginning of the "do". case 4: // Calls the Search case. scanf("\n\tEnter the label to be searched: %s", symbl); y=Search(symbl); printf("\n\tSearch Result:"); if(y==1) printf("\n\tThe label is present in the symbol table\n"); else printf("\n\tThe label is not present in the symbol table\n"); break; // Exists the Search case and reruns starting at the beginning of the "do". case 5: // If the user's input is invalid/doesn't match with any of the existing functions, the program exits/ends. exit(0); } } while(op<5); } /* and of main */ // Precondition: Two parameters: a key (string of characters) and an address (int). void Insert(char * symbl, int address) { struct SymbTab *p; p=malloc(sizeof(struct SymbTab)); strcpy(p->symbol,symbl); p->next=NULL; if (size==0) { first=p; last=p; } else { last->next=p; last=p; } size++; printf("\n\tLabel inserted\n"); } // Postcondition: Variable (with it's corresponding address) are added into the symbol table, and print statement is displatyed on the screen.
错误原因分析
- 未初始化指针的非法访问:
Insert函数中,p->symbol是未分配内存的空指针,直接用strcpy复制字符串会写入非法内存区域,这是段错误的核心原因。 - scanf参数错误:
main中scanf("%d", addrs)缺少取地址符&,会把输入值写入随机内存地址,引发崩溃或未定义行为。 - 输入处理混乱:
scanf("%d", &op)后会留下换行符,后续fgets会读取空行,导致symbl内容异常。 - 函数声明与定义不匹配:
Insert的声明是void Insert();,但定义是带参数的void Insert(char * symbl, int address),调用时会出现参数不匹配的未定义行为。 - 分支逻辑错误:
case 3中的if语句没有用大括号包裹,导致break会直接跳出switch,即使y==1也不会执行Delete操作。 - 错误的scanf用法:
case 4中用scanf输出提示字符串是错误的,应该先用printf提示,再用scanf读取输入。
修正后的完整代码
#include<stdio.h> #include<stdlib.h> #include<string.h> int size = 0; void Insert(char *symbl, int address); void Display(); void Delete(char *symbl); int Search(char *lab); void Modify(); struct SymbTab { char* symbol; int addr; struct SymbTab *next; }; struct SymbTab *first = NULL, *last = NULL; int main() { int op, y; int addrs; char symbl[30]; char dummy[2]; // 用于读取换行符 do { printf("\n\tSYMBOL TABLE IMPLEMENTATION\n"); printf("\n\t1.INSERT\n\t2.DISPLAY\n\t3.DELETE\n\t4.SEARCH\n\t5.END\n"); printf("\n\tEnter your option : "); scanf("%d", &op); // 读取scanf留下的换行符 fgets(dummy, sizeof(dummy), stdin); switch(op) { case 1: printf("Insert symbol: "); fgets(symbl, sizeof(symbl), stdin); // 去掉fgets读取的换行符 symbl[strcspn(symbl, "\n")] = '\0'; printf("Insert address: "); scanf("%d", &addrs); // 读取scanf留下的换行符 fgets(dummy, sizeof(dummy), stdin); Insert(symbl, addrs); break; case 2: Display(); break; case 3: printf("\n\tEnter the symbol to be deleted: "); fgets(symbl, sizeof(symbl), stdin); symbl[strcspn(symbl, "\n")] = '\0'; y = Search(symbl); if(y == 0) { printf("\n\tLabel not found\n"); } else if (y == 1) { Delete(symbl); } break; case 4: printf("\n\tEnter the label to be searched: "); fgets(symbl, sizeof(symbl), stdin); symbl[strcspn(symbl, "\n")] = '\0'; y = Search(symbl); printf("\n\tSearch Result:"); if(y == 1) { printf("\n\tThe label is present in the symbol table\n"); } else { printf("\n\tThe label is not present in the symbol table\n"); } break; case 5: exit(0); default: printf("\n\tInvalid option, try again\n"); } } while(op < 5); return 0; } void Insert(char *symbl, int address) { struct SymbTab *p = malloc(sizeof(struct SymbTab)); if(p == NULL) { printf("\n\tMemory allocation failed\n"); return; } // 为symbol分配内存并复制字符串 p->symbol = malloc(strlen(symbl) + 1); if(p->symbol == NULL) { free(p); printf("\n\tMemory allocation failed for symbol\n"); return; } strcpy(p->symbol, symbl); p->addr = address; p->next = NULL; if(size == 0) { first = p; last = p; } else { last->next = p; last = p; } size++; printf("\n\tLabel inserted\n"); } void Display() { struct SymbTab *temp = first; if(size == 0) { printf("\n\tSymbol table is empty\n"); return; } printf("\n\tSymbol\tAddress\n"); printf("\t----------------\n"); while(temp != NULL) { printf("\t%s\t%d\n", temp->symbol, temp->addr); temp = temp->next; } } int Search(char *lab) { struct SymbTab *temp = first; while(temp != NULL) { if(strcmp(temp->symbol, lab) == 0) { return 1; } temp = temp->next; } return 0; } void Delete(char *symbl) { struct SymbTab *temp = first, *prev = NULL; while(temp != NULL && strcmp(temp->symbol, symbl) != 0) { prev = temp; temp = temp->next; } if(temp == NULL) { printf("\n\tLabel not found\n"); return; } // 删除表头节点 if(prev == NULL) { first = first->next; if(first == NULL) { last = NULL; } } else { prev->next = temp->next; if(temp == last) { last = prev; } } free(temp->symbol); free(temp); size--; printf("\n\tLabel deleted\n"); }
关键修改说明
- 为
p->symbol分配内存:用malloc(strlen(symbl)+1)申请足够空间存储字符串(加1是为了存结束符\0),避免非法内存访问。 - 修正
scanf参数:给addrs加上取地址符&,确保输入写入正确内存。 - 处理输入换行符:用
fgets读取scanf留下的换行符,避免后续输入混乱;同时去掉fgets读取的换行符,保证字符串格式正确。 - 修正函数声明:让
Insert、Delete的声明与定义参数匹配,避免未定义行为。 - 修复分支逻辑:给
case3的if语句加上大括号,确保逻辑正确。 - 补全缺失的
Display、Search、Delete函数实现:原代码中这些函数只有声明没有实现,运行时会报错。
内容的提问来源于stack exchange,提问作者Zaynab B.
相关产品推荐
相关产品推荐

