2

我在尝试某事时得到了这个(只是为了理解)。请解释这种行为:


第一次尝试:

void main()    
{  
    char src[] = "vinay";
    int i;
    // char name[5] = "test";
    char *name=  "abcde";
    printf("%s \n", name);
    if (*(name+5) == '\0')
        printf("6th char is null\n");
    strcpy(name,src);
    printf("printcheck \n");
    for (i=0 ; i <6 ; i++)  
    {
        printf("%c \n", *(name+i));
    }
    printf("%s \n",name);    
}

输出:

abcde 
6th char is null
zsh: 16644 segmentation fault (core dumped)  a.out

第二次尝试:

void main()
{
    char src[] = "vinay";
    int i;
    char name[] = "pqrst";
    //char *name=  "abcde";
    printf("%s \n", name);

    if (*(name+5) == '\0')    
        printf("6th char is null\n");

    strcpy(name,src);
    printf("printcheck \n");

    for (i=0 ; i <6 ; i++)
    {
        printf("%c \n", *(name+i));
    }

    printf("%s \n",name);
}

输出:

pqrst 
6th char is null
printcheck     
v     
i   
n   
a     
y 
vinay

==================================================== ==========================================

问题:为什么它在尝试 1 时崩溃?我在 Solaris 机器内核版本上尝试这个:SunOS 5.8 Generic 117350-43 Oct 2006

4

8 回答 8

8

因为这种操作:

char name[] = "pqrst";

将常量字符串复制到堆栈上的数组。您可以自由修改本地副本。

但是,这种操作:

char *name=  "abcde";

只需将字符串的地址分配给指针。尝试修改该字符串是在尝试修改一个常量字符串,该字符串位于受保护的区域中,因此是不允许的。

于 2009-10-21T15:26:03.767 回答
5
char* name = "abcde";

分配一个指向您没有写入权限的常量内存空间的指针。

char name[] = "vinay"; 

分配一个可写数组。

于 2009-10-21T15:24:39.333 回答
5

字符串文字不可修改(在Undefined Behavior的惩罚下)。当你声明一个指向它们的指针时,你真的应该让它const

const char *name = "string literal";

引用标准:

6.4.5 String literals

6 .... If the program attempts to modify such an array,
  the behavior is undefined.
于 2009-10-21T15:26:23.340 回答
1

问题在于这一行:

char* name = "abcde";

该字符串"abcde"是一个静态 const字符串,它嵌入到可执行文件的一部分中,写入是非法的。当您这样做时strcpy(name, src),会strcpy尝试写入内存的静态部分,这会导致访问冲突。

另一方面,当你写这个时:

char[] name = "abcde";

thenname是在本地函数堆栈中分配的数组。你总是可以写入你的堆栈,所以这很好。

于 2009-10-21T15:26:19.347 回答
0

尝试 1 失败,因为您正在修改由编译器初始化的内存。使用引号char *name = "something"在常量内存空间中定义字符串(而不是在堆栈上,因为char name[] = "vinay" 您不应该修改它,因此当您尝试写入不可写区域时会出现分段错误。如果您想改用 achar *并使其可修改,而是自己分配内存:

char *name = NULL; 
name = (char *) malloc(6);

但以后不要忘记free()

于 2009-10-21T15:28:05.990 回答
0

在第一次尝试中,名称是指向 const 内存资源的指针。在第二次尝试中,您已经更改了它,并且在将文本放入该内存区域之前完成了分配。

动态分配通过以下方式完成:

char * buffer = malloc(STRING_SIZE);

或者

char buffer[STRING_SIZE];
于 2009-10-21T15:25:52.157 回答
0

它可能不一定是您没有为变量名分配空间的原因。您将 vinay 倾倒在堆栈上的一个随机区域的顶部,这很可能是为其他东西保留的。使用 malloc 为您的字符串分配空间,您应该没问题:)

于 2009-10-21T15:26:39.430 回答
0

字符串常量(“abcde”)可能位于只读数据段中,因此无法写入

char src[] = "vinay";
char *name = "abcde";
[...]
strcpy(name, src); /* copy string src to whatever name points to */

复制到只读内存位置会给你一个段错误。

第二个程序有效,因为现在目标内存区域位于所有局部变量所在的位置,并且该内存区域(堆栈)是可写的。

char src[] = "vinay";
char name[] = "abcde";
[...]
strcpy(name, src); /* copy string src to the memory area designated by name */
于 2009-10-21T15:26:52.830 回答