可能重复:
What is the difference between char a[] = “string” and char *p = “string”?
在堆栈内存和堆内存上使用memcpy有什么区别? 以下代码适用于Tru64但LINUX上的段错误
char * string2 = " ";
(void)memcpy((char *)(string2),(char *)("ALT=---,--"),(size_t)(10));
第二个版本适用于LINUX
char * string2 = malloc(sizeof(char)*12);
(void)memcpy((char *)(string2),(char *)("ALT=---,--"),(size_t)(10));
有人可以解释LINUX上的段错误吗?
答案 0 :(得分:7)
第一个示例包含未定义行为。因此它可能正常工作或显示任何随机行为。
<强>解释强>
第一个示例,向字符串文字声明指针string2
。字符串文字存储在Implementation定义的只读存储器位置中。不允许用户程序修改此内存。任何尝试都会导致未定义的行为。
参考:
C99标准6.4.5 / 5&#34;字符串文字 - 语义&#34;:
在转换阶段7中,将值为零的字节或代码附加到由字符串文字或文字产生的每个多字节字符序列。然后使用多字节字符序列初始化静态存储持续时间和长度的数组,该数组足以包含序列。对于字符串文字,数组元素的类型为char,并使用多字节字符序列的各个字节进行初始化;对于宽字符串文字,数组元素的类型为wchar_t,并使用宽字符序列进行初始化...
如果这些数组的元素具有适当的值,则未指定这些数组是否相同。 如果程序试图修改此类数组,则行为未定义。
答案 1 :(得分:2)
在第一个示例中,指针和实际字符串内容之间必须不同:尽管指针(string2
)在堆栈上,但实际的字符串字节不是。它们在常量区域中是一个很好的变化,它是只读的,因此是段错误。
答案 2 :(得分:2)
首先,行为未定义。从C99,6.4.5 / 6:
未指明这些数组是否与它们不同 元素具有适当的值。如果程序试图 修改这样的数组,行为是未定义的。
实际上,操作系统选择在只读存储器中加载相关的图像部分;因此当你尝试写时会出现段错误。
答案 3 :(得分:1)
在第一个示例中,您不在堆栈内存中,而是在.rodata
(只读数据)部分。字符串文字具有静态存储持续时间,不需要是可修改的。
void foo(void)
{
// string array has automatic storage duration
char string[] = " ";
// string2 pointer has automatic storage duration and points to
// a string literal that a static storage duration
char *string2 = " "; // string2 pointer has
}
答案 4 :(得分:1)
在第一种情况下,memcpy的目的地是一个字符串文字,正如其他人所指出的那样。
在第二种情况下:不要施放不必要的。避免魔术常数。 Sizeof(char)== 1.
#include <stdlib.h>
#include <string.h>
char * string2 = malloc(1+strlen("ALT=---,--"));
(void)memcpy(string2, "ALT=---,--"), 1+strlen("ALT=---,--") );
,相当于:
char * string2 = malloc(1+strlen("ALT=---,--"));
(void)strcpy(string2, "ALT=---,--") );
BTW:原来,常数'10'太小了;不会复制终止的nul字节,并且字符串将是未终止的。
答案 5 :(得分:1)
你可以试试这个:
char string2[] = " ";
(void)memcpy((char *)string2,(char *)("ALT=---,--"),(size_t)(10));
答案 6 :(得分:0)
将您的第一个示例更改为:
char string2 [] = " ";
(void)memcpy((char *)(string2),(char *)("ALT=---,--"),(size_t)(10));
然后你将比较堆栈内存和堆内存。