對字元串常量進行修改
#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