为什么在我仍然能够访问这些位置时出现段错误?
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 )
我正在尝试使用两个指向同一字符串的指针就地反转字符串。第一个(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 )