strcpy()的分段错误
这项工作:strcpy()的分段错误,c,strcpy,C,Strcpy,这项工作: int main() { char *t = "Hello"; t = "World"; printf("%s", t); } 但这给了细分错误: int main() { char *t = "Hello"; strcpy(t, "World"); // the only difference printf("%s", t); } 为什么?在第一个示例中,指针t指向字符串常量“Hello”,然后立即指向字符
int main()
{
char *t = "Hello";
t = "World";
printf("%s", t);
}
但这给了细分错误:
int main()
{
char *t = "Hello";
strcpy(t, "World"); // the only difference
printf("%s", t);
}
为什么?在第一个示例中,指针
t
指向字符串常量“Hello”
,然后立即指向字符串常量“World”
;然后打印后一个值
第二个示例中的代码因segfault崩溃,因为字符串常量不可写。(strcpy尝试修改保存文本的内存“Hello”
)。GCC将字符串常量放入只读部分,除非使用-fwriteable strings
编译
代码
char *test = "Hello";
表示编译器+链接器在只读节中放置一个字节字符串“Hello\0”,并且test
指向其中的第一个字符。任何试图写入此指针的行为都将受到操作系统的严厉惩罚
另一方面
char test[] = "Hello";
声明一个由6个字符组成的数组,初始值为({'H','e','l','l','o','\0'}
)
一些旧程序假设字符串常量是可写的;因此,要求GCC支持使用
-fwriteable strings
命令行开关编译这些程序。首先将t
的值更改为从“Hello”
的地址指向“World”
的地址。第二个尝试覆盖数据本身。“Hello”是一个字符串常量。根据常量的定义,它不是用来写的
在第一个示例中,“t”是一个指针,它可以指向(分配)字符串常量。您明确定义的字符串(例如,
“Hello”
)通常放置在只读内存区域中。这些字符串不能更改
在第一个示例中,您没有将“Hello”字符串更改为“World”字符串。您正在重新分配t
,以便它指向“World”而不是“Hello”。“Hello”字符串仍然挂在只读内存中,未被触动
以下是初始状态:
t -> "Hello"
"World"
这是第二种状态:
"Hello"
t -> "World"
在第二个示例中,您试图覆盖“Hello”字符串。这是不可能做到的
您应该将声明从char*t
更改为const char*t
。我认为可以将GCC配置为强制执行此操作。在char*t=“Hello”
t
中,在只读位置分配“Hello”。因此,写入只读位置会导致分段错误
分配和复制之间有区别
第一个示例是您试图将另一个字符串的地址分配给t
在第二个示例中,您试图写入只读位置
使用chart[]=“Hello”
。在这里,t可以被覆盖
更多说明赋值
t=“World”
仅更改指针,而strcpy
更改t指向的内存。字符串文字可能位于只读段中。char*t
是指针。在第一个示例中,您只是将指针从一个字符串文本分配到另一个字符串文本:首先t
指向“Hello”
,然后指向“World”
。这是完全合法的
但是,字符串文字本身就是文字——它们不能更改。通常,它们位于内存的只读部分。在第二个示例中,您试图更改分配给字符串literal
“Hello”
的内存中的内容,方法是用“World”
覆盖它。这是非法的,你会得到一个分割错误 那么第一个程序(t=“world”)@user2076561呢?因为p
是一个指针,它与字符串文字不同。@user2076561在第一个程序中,您不是在写“world”
以前的“Hello”
,而是将指针指向其他地方。char*t=“Hello”;“是一个指针,指向一个
string literal。你可以自由地将它分配给另一个
string literal`但不能将一些数据(例如字符串)存储在内存中。这就是答案的本质,我认为下面的答案中有人投了反对票——如果是你——请去把它投回去。”。