天天看點

c 語言中對字元串常量修改的錯誤原因解析

對字元串常量進行修改

#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
           

繼續閱讀