为何我的C语言基础代码触发Segmentation Fault(段错误)?
解决squeeze函数的段错误问题
问题描述
要实现squeeze(char s1[], char s2[])函数,功能是删除s1中所有出现在s2里的字符并打印结果。但运行代码时,在s1[j] = s1[i];行触发Segmentation Fault,拆分代码后确认段错误出现在s1[j]行。排查后认为未访问越界数组索引,用gdb也能读取s1[j]和s1[i],刚学C不知道问题所在。
原代码
#include <stdio.h> void squeeze(char s1[], char s2[]); int main() { squeeze("test string", "ts"); return 0; } void squeeze(char s1[], char s2[]) { int i, j, k; for (k = 0; s2[k] != '\0'; k++) { for (i=j=0; s1[i] != '\0'; i++) if (s1[i] != s2[k]) { s1[j] = s1[i]; ++j; } s1[j] = '\0'; } printf("%s", s1); }
GDB报错信息
Program received signal SIGSEGV, Segmentation fault. squeeze (s1=0x555555556007 "test string", s2=0x555555556004 "ts") at main.c:18 18 s1[j] = s1[i];
问题原因
核心问题是字符串字面量是只读的:
你在main函数中传入的"test string"是字符串字面量,它被存储在程序的只读数据段中。C语言中,字符串字面量本质是const char*类型,即使编译器允许用char[]接收,也不允许修改其内容。当你的代码尝试通过s1[j] = s1[i];修改这块只读内存时,操作系统会触发段错误(SIGSEGV)来阻止非法写操作。
解决方案
将传入的字符串字面量改为可修改的字符数组,让s1指向栈上的可写内存区域:
修改后的代码
#include <stdio.h> void squeeze(char s1[], char s2[]); int main() { char s1[] = "test string"; // 定义为可修改的字符数组,复制字符串字面量到栈上 squeeze(s1, "ts"); return 0; } void squeeze(char s1[], char s2[]) { int i, j, k; for (k = 0; s2[k] != '\0'; k++) { for (i=j=0; s1[i] != '\0'; i++) if (s1[i] != s2[k]) { s1[j] = s1[i]; ++j; } s1[j] = '\0'; } printf("%s", s1); }
解释
定义char s1[] = "test string";时,编译器会在栈上分配足够的内存,把字符串字面量"test string"的内容复制到这个数组中。此时s1指向的是栈上的可写内存,后续修改s1的操作就不会触发段错误了。
内容的提问来源于stack exchange,提问作者superslime16th
相关产品推荐
相关产品推荐

