C语言SIGBUS错误(退出码138)求助:字符串修改函数运行异常
错误原因与解决方法:SIGBUS信号触发的字符串字面量修改问题
错误原因
- 你在
main里传递的"abcdefghigk"是字符串字面量,C标准中这类字符串被存储在只读内存区域(程序的.rodata段),不允许被修改。 - 你的
squeeze函数里直接执行了s[j++] = s[i]和s[j] = '\0'的写操作,属于违规修改只读内存的未定义行为,在M1架构的MacOS上触发了SIGBUS(总线错误),程序直接中断,因此没有任何输出。
两种修复方案
方案一:用可写的字符数组替代字符串字面量
把main里的字符串改成字符数组,这样内存是可写的,直接复用你原来的squeeze函数即可:
#include <stdio.h> void squeeze(char s[], int c) { int i, j; for (i = j = 0; s[i] != '\0'; i++) { if (s[i] != c) s[j++] = s[i]; } s[j] = '\0'; printf("Converted: %s\n", s); } int main() { char str[] = "abcdefghigk"; // 字符数组,内存可写 squeeze(str, 'c'); return 0; }
方案二:让函数返回新字符串(不修改原字符串)
如果不想改动原字符串,可以让函数动态分配内存生成新字符串,调用后记得释放内存避免泄漏:
#include <stdio.h> #include <stdlib.h> #include <string.h> char* squeeze(const char s[], int c) { // 先计算新字符串的长度 int new_len = 0; for (int i = 0; s[i] != '\0'; i++) { if (s[i] != c) new_len++; } // 分配内存(多留1位存储终止符'\0') char* result = malloc(new_len + 1); if (!result) return NULL; // 处理内存分配失败的情况 int j = 0; for (int i = 0; s[i] != '\0'; i++) { if (s[i] != c) result[j++] = s[i]; } result[j] = '\0'; return result; } int main() { const char* str = "abcdefghigk"; char* squeezed_str = squeeze(str, 'c'); if (squeezed_str) { printf("Converted: %s\n", squeezed_str); free(squeezed_str); // 释放动态分配的内存 } return 0; }
额外提示
- 以后声明字符串字面量时,尽量用
const char*,编译器会帮你检查出试图修改只读内存的错误,提前规避问题。 - 不同系统对修改只读内存的反应可能不同,有的会触发
SIGSEGV(段错误),但核心原因都是触碰了不允许修改的内存区域。
内容的提问来源于stack exchange,提问作者ALAN WING
相关产品推荐
相关产品推荐

