为什么在我仍然能够访问这些位置时出现段错误?

Why am getting segfault while I am still able to access those location?

我正在尝试使用两个指向同一字符串的指针就地反转字符串。第一个(char *p)指向字符串的起始位置,第二个(char *q)指向字符串的结束位置。因此,当我尝试使用 gdb 进行调试时,我在第 16 行遇到分段错误。

当我尝试打印 *p*q 的值时,它工作正常。为什么在我仍然可以访问这些位置的同时出现段错误?

Breakpoint 1, main () at reverse.c:16
16          *q = *p;
(gdb) print p
 = 0x5555555547e4 "hello"
(gdb) print q
 = 0x5555555547e8 "o"
(gdb) step

Program received signal SIGSEGV, Segmentation fault.
0x00005555555546db in main () at reverse.c:16
16          *q = *p;

程序实际代码为

#include<stdio.h>

int main() {
    char *array = "hello";

    char *p=&array[0];// pointer to the first element

    // Make q point to last value of the array
    char *q = &array[0];
    while(*q) q++; 

    char temp;
    q--; // move left so that we don't point to `[=11=]`
    while(p<q){ 
        temp = *p;
        *q = *p;
        *p = temp; 
        p++;q--;    
    }

    printf(" Done reversing \n");
}

您称为 array 的字符串实际上并不是一个字符数组,而是一个字符串文字,根据平台的不同,它是不可写的。所以将其更改为

char array[] = "Hello";

char *array = "string"char array[] = "string"有区别。

  • char *array = "string""string" 放入内存的 read-only 部分,并使 array 指向它。因此,任何更改 array 指向的内存内容的尝试都将导致段错误(换句话说是非法的)。
  • char array[] = "string""string" 放入内存的 read-only 部分并 复制 它到 array 指向的堆栈上新分配的内存。因此,对内存进行更改array 是指向合法的。

您可能还想看看 this post

您正在尝试更改字符串文字

char *array = "hello";

指针指向array

虽然在 C(与 C++ 相反)中,字符串文字具有 non-constant 字符数组的类型,但是您不能更改字符串文字。任何更改字符串文字的尝试都会导致未定义的行为。

您应该声明一个字符数组并用字符串文字对其进行初始化。例如

char array[] = "hello";

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    char array[] = "hello";

    puts( array );

    char *q = array;
    while ( *q ) ++q;

    for ( char *p = array; p < --q; ++p )
    {
        char c = *p;
        *p = *q;
        *q = c;
    }

    puts( array );

    return 0;
}

它的输出是

hello
olleh

而且你程序中交换字符的代码片段是错误的

    temp = *p;
    *q = *p;
    *p = temp; 

一定有

    temp = *p;
    *p = *q;
    *q = temp; 

并且由于变量 temp 仅在 while 循环中使用,其声明区域应受 while 循环的块范围限制。

while(p<q){ 
    char temp = *p;
    *p = *q;
    *q = temp; 
    p++;q--;    
}

考虑到根据 C 标准,不带参数的函数 main 应声明为

int main( void )