Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
char*导致segfault,但char[]不';T_C_String_Segmentation Fault - Fatal编程技术网

char*导致segfault,但char[]不';T

char*导致segfault,但char[]不';T,c,string,segmentation-fault,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

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

我编写了一个返回字符串的函数。我将一个
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]
,我在堆栈上分配了足够的空间容纳100个字符,因此
strcpy()
可以愉快地写入
file\u name\u out

我说得对吗

据我所知,char*filename=“”;创建只读 一串然后strcpy()尝试写入只读变量, 这是不允许的,因此错误是有意义的

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

但是当我写char*filename;,会发生什么呢?我猜是这样 堆栈上分配了足够的空间来容纳指向字符的指针,因此 我只能在文件名中写一个字符 变数


分配足够的空间来存储指向字符的指针,就这样。您不能写入
*filename
,甚至不能写入一个字符,因为您没有分配空间来存储
*filename
指向的内容。如果要更改文件名所指向的内容,首先必须将其初始化为指向有效的位置。

字符文件名[100]创建100个字符的连续数组。在本例中,
file\u name
是一个类型为(char*)的指针,它指向数组中的第一个元素


char*文件名创建指针。但是,它没有初始化为特定的内存地址。此外,这个表达式不分配内存。

我认为这里的问题是

char string[100];
将内存分配给字符串-您可以使用字符串作为指针访问该字符串 但是

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

要获得内存,您可以使用

string = calloc(100,sizeo(char));
例如,但您需要在最后记住以释放内存

free(string);
或者你可能会出现内存泄漏

另一个内存分配路由是malloc

总而言之

char string[100];
相当于

char * string;
string = calloc(100,sizeo(char));
...
free(string);
虽然严格来说,calloc将所有元素初始化为零,但在字符串[100]十进制中,数组元素未定义,除非使用 字符串[100]={} 如果使用malloc对内存进行分级,则内容未定义

@PaulRooney提出的另一点是,char string[100]给出堆栈上的内存分配,而calloc使用堆

什么也不分配。它只是一个指向未指定位置的指针(该值是该内存中以前的值)。使用此指针将永远无法工作,因为它可能指向您的程序允许使用的内存范围之外

char *filename = "";
指向一段程序数据段。正如您已经说过的,它是只读的,因此尝试更改它会导致SEGFULT


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

“但是如果我将char file_name[100];替换为char*filename;或char*filename=“”;则strcpy()中会出现分段错误。“-char*filename没有分配内存;这只是一个指针看看内存分配,在
malloc
函数中以及如何使用它。“我猜堆栈上分配了足够的空间来容纳指向字符的指针,所以我只能写一个字符”-第一部分正确,第二部分错误。指针的值是它所持有的地址。。声明一个而不初始化会使指针不确定。它不包含有效内存区域的已知地址。取消引用它会调用未定义的行为(阅读或写作没有区别)。啊,是的,我编辑了这个问题。所以这是正确的说法:如果我定义了变量指向的位置,我可以在变量指向的地方写一个字符。在这种情况下,file_name是一个类型为(char*)的指针。不是真的<代码>文件名
的类型为
char[100]
。数组和指针并不总是可互换的。可以说,在大多数情况下,
file\u name
将衰减为指向第一个元素的指针。但它不是指向char的指针。如果
文件名
是一个
字符*
,那么
文件名
将是一个
字符**
,而事实上它是一个
字符(*)[100]
。注意
字符字符串[100]之间的差异可能也很重要
calloc
分配是一个在堆栈上,而另一个在堆上。谢谢@PaulRooney-将编辑放入。。。
char * string;
string = calloc(100,sizeo(char));
...
free(string);
char *filename; 
char *filename = "";