char *导致段错误,但char []不会

时间:2015-05-18 10:23:29

标签: c string segmentation-fault

我想我知道自己问题的答案,但我想确认我完全明白这一点。

我写了一个返回字符串的函数。我传递char*作为参数,函数修改指针。

它工作正常,这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void get_file_name(char* file_name_out)
{
    char file_name[12+1];
    char dir_name[50+12+1];

    strcpy(file_name, "name.xml");
    strcpy(dir_name, "/home/user/foo/bar/");
    strcat(dir_name, file_name);

    strcpy(file_name_out, dir_name); // Clarity - equivalent to a return
}

int main()
{
    char file_name[100];

    get_file_name(file_name);
    printf(file_name);

    return 0;
}

但如果我将char file_name[100];替换为char *filename;char *filename = "";,我会在strcpy()中收到细分错误。

我不确定为什么?

我的功能将char*作为参数并so does strcpy()

As far as I understandchar *filename = "";创建一个只读字符串。 strcpy()然后尝试写入只读变量,这是不允许的,因此错误是有意义的。

但是当我写char *filename;时会发生什么?我的猜测是,在堆栈上分配了足够的空间来容纳指向char的指针,所以我只能写一个单file_name_out点的单个字符。对strcpy()的调用将尝试写入至少2,因此错误。

这将解释为什么以下代码编译并产生预期的输出:

void foo(char* a, char* b)
{
    *a = *b;
}

int main()
{
    char a = 'A', b = 'B';
    printf("a = %c, b = %c\n", a, b);
    foo(&a, &b);
    printf("a = %c, b = %c\n", a, b);
    return 0;
}

另一方面,如果我使用char file_name[100];,我会在堆栈上为100个字符分配足够的空间,因此strcpy()可以愉快地写入file_name_out

我是对的吗?

4 个答案:

答案 0 :(得分:4)

  

据我了解,char * filename =&#34;&#34 ;;创建只读   串。 strcpy()然后尝试写入只读变量,   这是不允许的,所以错误是有道理的。

是的,没错。它与声明一个字符数组本质上是不同的。初始化字符串文字的字符指针使其成为只读;尝试更改字符串的内容会导致UB。

  

但是当我写char * filename时会发生什么? ?我的猜测是   在堆栈上分配了足够的空间来容纳指向char的指针,所以   我只能在我的file_name_out中写一个字符   变量

您分配了足够的空间来存储指向角色的指针,而这就是它。您无法写入*filename,甚至不能写入单个字符,因为您没有分配空间来存储*filename指向的内容。如果要更改filename指向的内容,首先必须将其初始化为指向某个有效的位置。

答案 1 :(得分:2)

我认为这里的问题是

char string[100];

将内存分配给字符串 - 您可以使用字符串作为指针来访问它 但是

char * string;

不会将任何内存分配给字符串,因此会出现seg错误。

获取可以使用的记忆

string = calloc(100,sizeo(char));
例如

,但你需要记住最后用

释放内存
free(string);

或者你可能会发生内存泄漏。

另一个内存分配路由是malloc

总结

char string[100];

相当于

char * string;
string = calloc(100,sizeo(char));
...
free(string);

虽然严格来说calloc将所有元素初始化为零,而在字符串[100] decalaration中,数组元素是未定义的,除非你使用     串[100] = {} 如果您使用malloc代替渐变内存,则内容未定义。

@PaulRooney提出的另一点是char字符串[100]在堆栈上提供内存分配,而calloc使用堆。 For more information about the heap and stack see this question and answers ...

答案 2 :(得分:0)

char file_name[100];创建一个包含100个字符的连续数组。在这种情况下,file_name是一个指向类型(char *)的指针,它指向数组中的第一个元素。

char* file_name;创建一个指针。但是,它未初始化为特定的内存地址。此外,该表达式不分配内存。

答案 3 :(得分:0)

char *filename; 

什么都不分配。它只是一个指向未指定位置的指针(该值是之前该存储器中的任何值)。使用此指针将永远不会起作用,因为它可能指向允许程序使用的内存范围之外。

char *filename = "";

指向一段程序数据段。正如你已经说过的那样它是只读的,所以试图改变它会导致段错误。

在最后一个示例中,您处理的是单个char值,而不是char值字符串,而您的函数foo则将它们视为这样。因此char *值指向的缓冲区长度没有问题。