第 1 部分
int main(int argc, char **argv)
{
int fd;
int i;
char *line;
if (!(fd = open(argv[1], O_RDWR | O_CREAT)))
{
printf("Error in open\n");
return (0);
}
while ((i = get_next_line(fd, &line)) > 0)
{
printf("%i-%s\n",i, line);
free(line);
}
printf("%i-%s",i, line);
free(line);
}
第 2 部分
int main(int argc, char **argv)
{
int fd;
int i;
char **line;
if (!(fd = open(argv[1], O_RDWR | O_CREAT)))
{
printf("Error in open\n");
return (0);
}
while ((i = get_next_line(fd, line)) > 0)
{
printf("%i-%s\n",i, *line);
free(*line);
}
printf("%i-%s",i, *line);
free(*line);
}
<小时/>
第1部分和第2部分有什么区别吗?它们之间的区别是一个使用**line
,另一个仅使用*line
。
根据我的理解,两者应该是相同的。
我正在使用它们来测试我自己的读取并返回 1 行的函数的实现。
问题:
第 1 部分测试运行良好。 第 2 部分段错误测试结果
两者的 get_next_line()
实现保持相同。
最佳答案
在第一种情况下,使用&line
将有效地址传递给get_next_line
。但在第二种情况下,使用 line 将未初始化的变量传递给函数。您没有显示 get_next_line
但我认为它会执行类似 *line = blah
的操作,如果传入 line
值,这当然会出现段错误不是一个有效的地址(从技术上讲,取消引用未初始化的指针是未定义的行为,因此它可能会出现段错误,但也可能表现出任何其他行为)。
另一种看待它的方式:
char **line;
get_next_line(fd, line);
printf("%i-%s\n",i, *line);
这基本上就是第二种情况的作用。我们知道在 C 中函数参数是按值传递的。因此 get_next_line
无法更改调用者的 line
变量的值。因此,当函数返回时,line 的值是未定义的,因为它从未初始化。因此,即使 get_next_line
不取消引用 line
,printf
仍然会导致未定义的行为,因为它取消引用 line
但它的值那时显然未定义。
将其与第一种情况进行比较,其中等效操作是:
char *line;
get_next_line(fd, &line);
printf("%i-%s\n",i, *line);
在这种情况下,get_next_line
能够有效地更改调用者的 line
变量,如下所示:
*line = malloc(MY_MAX_LINE_LENGTH);
因此,当函数退出时,调用者的 line
变量现在具有有效的内存地址,因此可以安全地取消引用。
关于c - 为什么使用 char** 会导致 char* 工作时出现段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59022713/