为何可访问内存地址却触发段错误?原地反转字符串问题排查
为什么能访问字符串指针地址却触发段错误?
你遇到的这个问题,核心原因大概率是你尝试修改的字符串是存储在只读内存区域的字符串字面量——这是C语言里非常容易踩的经典坑!
最常见的场景:字符串字面量的只读属性
假设你的代码是类似这样的:
#include <stdio.h> #include <string.h> int main() { char *str = "hello world"; // 这里是字符串字面量,被存在只读数据段 char *p = str; char *q = str + strlen(str) - 1; while (p < q) { char temp = *p; *p = *q; // 第16行,触发段错误 *q = temp; p++; q--; } printf("%s\n", str); return 0; }
在C语言中,用char *str = "xxx"定义的字符串字面量,会被编译器放到程序的**只读数据段(.rodata)**里。这个内存区域的权限是只读的:
- 你可以正常读取它的内容(所以
gdb里print *p和print *q能输出正确值) - 但一旦尝试写入修改(比如
*q = *p),操作系统的内存保护机制就会触发段错误(SIGSEGV),直接阻止你修改只读内存。
这就像你能翻阅图书馆的书,但绝对不能在书上乱写——读取权限有,写入权限完全没有。
怎么解决?
把字符串放到可写的内存区域就行,有两种常用方式:
- 用字符数组存储字符串:
char str[] = "hello world"; // 此时字符串会被复制到栈上的数组,完全可读写
- 动态分配堆内存:
#include <stdlib.h> char *str = malloc(strlen("hello world") + 1); strcpy(str, "hello world"); // 把字面量复制到堆内存,可读写 // 记得用完后调用free(str)释放内存
其他小概率排查方向
如果你确定不是字符串字面量的问题,那可以检查这两个点:
- 指针q越界:比如计算末尾位置时出错,q指向了字符串范围外的地址。你可以在
gdb里用print q和print str + strlen(str) -1对比,确认指针地址是否一致。 - 内存区域被破坏:比如字符串所在的内存已经被提前释放,或者被其他操作篡改,但这种情况通常读取也会出问题,和你描述的“能正常打印*p/*q”不太匹配。
内容的提问来源于stack exchange,提问作者BODDU MANOHAR REDDY
相关产品推荐
相关产品推荐

