C语言汇编器get_label函数触发SIGSEGV段错误求助
问题:汇编器get_label函数触发段错误(SIGSEGV)
开发C语言汇编器时,get_label函数处理以下汇编文件第二行的LOOP:时触发SIGSEGV(段错误),但第一行的MAIN:可正常处理。怀疑是内存问题,但作为新手不知如何排查。试过strdup函数无效,改用自定义PUT_WORD宏配合malloc实现后仍未解决,寻求修复方法及相关建议。
测试用汇编文件内容
MAIN: mov @r3 ,LENGTH LOOP: jmp L1 mcro m1 ...rest of file
get_label函数代码
char *get_label(char *token) { char *label; label = (char *) malloc(MAX_LABEL_LEN); //<-- THIS LINE if (label == NULL) { printf("ERROR: Memory allocation failed for label in line %d.\n", line_count); } char *label_ptr = label; PUT_WORD(label_ptr, token); if(is_label_decleration(label)) { label[strlen(label) - 1] = '\0'; } if (get_commend(label) != NOT_OPCODE) {/*checks if the label is a command name*/ valid_file = NOT_VALID; printf("ERROR: the label %s with invalid name at line %d, can't use command keyword as label\n", label, line_count); return NULL; } if (!isalpha(*label)) { valid_file = NOT_VALID; printf("ERROR: the label %s with invalid name at line %d, can't start label with non letter character\n", label, line_count); return NULL; } label_ptr = label; while (isalnum(*++label_ptr)); if (*label_ptr != '\0') { valid_file = NOT_VALID; printf("ERROR: the label %s with invalid name at line %d, can't have label with non letter or digit character\n", label, line_count); return NULL; } return label; }
问题分析与修复建议
核心问题点
- malloc失败未终止流程:当
malloc返回NULL时,仅打印错误但继续执行后续代码,操作空指针直接触发段错误。 - PUT_WORD宏的安全性问题:如果宏未正确给字符串添加终止符
\0,strlen会读取越界;若token长度超过MAX_LABEL_LEN-1,会导致缓冲区溢出。 - 字符串长度未检查:调用
label[strlen(label)-1]前未判断字符串长度,若label为空,会访问label[-1]触发段错误。 - 循环越界风险:
while (isalnum(*++label_ptr))未先检查是否到达字符串终止符,若字符串无\0,会持续读取非法内存。
具体修复步骤
- 处理malloc失败的情况:分配失败后直接返回NULL,避免后续操作空指针
if (label == NULL) { printf("ERROR: Memory allocation failed for label in line %d.\n", line_count); return NULL; // 新增返回逻辑 }
- 替换为安全的字符串复制:避免PUT_WORD的潜在问题,用
strncpy确保不溢出并手动添加终止符
// 替换PUT_WORD(label_ptr, token); strncpy(label, token, MAX_LABEL_LEN - 1); label[MAX_LABEL_LEN - 1] = '\0'; // 强制终止,防止溢出
- 添加字符串长度检查:修改标签处理逻辑,避免访问非法内存
if(is_label_decleration(label)) { size_t len = strlen(label); if (len > 0) { label[len - 1] = '\0'; } else { valid_file = NOT_VALID; printf("ERROR: Empty label declaration at line %d.\n", line_count); free(label); // 释放已分配内存 return NULL; } }
- 修复循环逻辑:先检查终止符,再判断字符类型,避免越界
label_ptr = label; while (*label_ptr != '\0' && isalnum(*label_ptr)) { label_ptr++; } if (*label_ptr != '\0') { valid_file = NOT_VALID; printf("ERROR: the label %s with invalid name at line %d, can't have label with non letter or digit character\n", label, line_count); free(label); // 释放内存 return NULL; }
- 内存泄漏防护:所有错误分支返回NULL前,记得用
free(label)释放已分配的内存,避免内存泄漏。
调试建议
用gdb工具定位崩溃点:
- 编译程序时添加
-g参数生成调试信息:gcc -g your_assembler.c -o assembler - 运行
gdb ./assembler,输入run test.asm启动程序 - 崩溃后输入
bt查看调用栈,确认具体是哪一行代码触发的段错误,精准定位问题。
内容的提问来源于stack exchange,提问作者Itay Segev
相关产品推荐
相关产品推荐

