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); }
为什么?
您明确定义的字符串 – 例如"Hello"
– 通常放在只读存储器的区域中。 这些字符串无法更改。
在第一个示例中,您没有将“Hello”字符串更改为“World”字符串。 您正在重新分配t
,使其指向 “World”而不是“Hello”。 “Hello”字符串仍然在未读取的内存中闲置。
这是初始状态:
t -> "Hello" "World"
这是第二个状态:
"Hello" t -> "World"
在第二个示例中,您尝试覆盖“Hello”字符串。 这是不可能做到的。
您应该将声明从char *t
更改为const char *t
。 我认为GCC可以配置为强制执行此操作。
第一个将t
的值更改为从"Hello"
的地址指向"World"
的地址。 第二次尝试覆盖数据"Hello"
本身。
在第一个例子中,指针t
指向一个字符串常量"Hello"
,然后立即指向字符串常量"World"
; 然后打印后一个值。
第二个示例中的代码与segfault崩溃,因为字符串常量不可写。 (strcpy尝试修改包含文本"Hello"
的内存)。 除非使用-fwriteable-strings
编译,否则GCC会将字符串常量放入只读部分。
代码
char *test = "Hello";
表示编译器+链接器在只读部分中放置一串字节“Hello \ 0”, test
指向其第一个字符。 任何通过此指针写入的尝试都会受到操作系统的严厉惩罚。
另一方面
char test[] = "Hello";
声明一个包含6个字符的数组,初始值为( { 'H', 'e', 'l', 'l', 'o', '\0' }
)。
一些旧程序假设字符串常量是可写的; 因此要求GCC支持使用-fwriteable-strings
命令行开关编译这些程序。
赋值t = "World"
仅更改指针,而strcpy
更改t指向的内存。 字符串文字可能位于只读段中。
char* t
是一个指针。 在第一个示例中,您只是将指针从一个字符串文字指定给另一个字符串:首先指向"Hello"
,然后指向"World"
。 这完全合法。
但是,字符串文字本身就是文字 – 它们无法更改。 通常它们位于内存的只读部分。 在第二个示例中,您尝试通过用"World"
覆盖它来更改分配给字符串文字"Hello"
的内存中的内容。 这是非法的,你会得到一个分段错误。
在char *t="Hello"
Hello”中,在只读位置分配“Hello”。 因此,写入只读位置会导致分段错误。
分配和复制之间有区别。
您尝试将另一个字符串的地址分配给t
第一个示例。
在第二个示例中,您尝试写入只读位置。
使用char t[] = "Hello"
。 这里可以覆盖
更多解释在这里
“Hello”是一个字符串常量。 它并不意味着通过常量的定义来写。
在你的第一个例子中,’t’是一个指针,它可以指向(被赋值)字符串常量。