对字符串常量进行修改
#include <stdio.h>
int main()
{
char *a = "hello"; // 字符串常量
a[0] = 'w';
printf("%s\n", a);
return 0;
}
运行以上代码会出现如下错误: Segmentation fault
,即段错误。
错误解析
将上述代码编译成汇编代码如下。从中可以看出,字符串常量被声明在 rodata 节,即只读数据节(read only data)。因此尝试对字符串修改,即会引发段错误。
.section .rodata ; 只读数据节开始
.LC0:
.string "hello" ; 声明的字符串常量 char *a = "hello";
.text
.globl main
.type main, @function
main:
.LFB0:
pushl %ebp
movl %esp, %ebp
subl $20, %esp
movl $.LC0, -12(%ebp)
movl -12(%ebp), %eax
movb $119, (%eax) ; 尝试对字符串修改 a[0] = 'w';
subl $12, %esp
pushl -12(%ebp)
call puts
addl $16, %esp
movl $0, %eax
对字符串数组进行修改
include <stdio.h>
int main()
{
char a[]="hello";
a[0] = 'w';
printf("%s\n", a);
return 0;
}
将其编译成汇编如下,可以看出,字符串被拷贝到堆栈上,因此对其修改没有问题。
main:
pushl %ebp
movl %esp, %ebp
movl $1819043176, -18(%ebp) ; $ebp-18 = "hell"
movw $111, -14(%ebp) ; $ebp-14 = "o\0"
movb $119, -18(%ebp) ; a[0] = 'w';
subl $12, %esp
leal -18(%ebp), %eax
pushl %eax
call puts
addl $16, %esp
movl $0, %eax