使用memmove处理重叠字符串触发段错误,求排查问题原因
问题描述
编写程序时需要复制重叠字符串,选用memmove但运行触发段错误,测试代码如下:
#include <stdio.h> #include <string.h> int main () { char* s = "foobar"; // 7 bytes memmove(s, s+1, 6); printf("%s\n", s); return 0; }
预期输出oobar,但执行触发段错误,调整第三个参数仍报错。valgrind提示:
==36627== Bad permissions for mapped region at address 0x10A004 ==36627== at 0x4852A13: memmove (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==36627== by 0x10917B: main (in /home/[..]/tmp)
刚接触valgrind,仅确定段错误由memmove引发,请问哪里操作出错了?
问题原因与解决方法
- 核心错误:
char* s = "foobar";定义的是字符串字面量,这类数据会被编译器放到程序的只读数据段(.rodata)中,不允许修改。memmove尝试向只读内存写入数据,直接触发权限错误,也就是valgrind提示的Bad permissions for mapped region。 - 解决办法:把字符串定义为栈上的可修改数组,替换成
char s[] = "foobar";。此时字符串会被复制到栈内存中,具备读写权限,memmove就能正常执行重叠内存的复制操作。
修改后的代码:
#include <stdio.h> #include <string.h> int main () { char s[] = "foobar"; // 栈上的可修改数组,包含7字节空间 memmove(s, s+1, 6); printf("%s\n", s); return 0; }
运行后会输出预期的oobar。
内容的提问来源于stack exchange,提问作者VirtualCode
相关产品推荐
相关产品推荐

