为什么使用 char** 会导致 char* 工作的段错误?
Why does using a char** cause a segfault where a char* works?
第 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);
}
Part 1 和Part 2 有什么区别吗,区别是一个使用**line
,另一个只是*line
。
根据我的理解,两者应该是一样的。
我正在使用它们来测试我自己的函数实现,该函数读取 return 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
变量的值。所以当函数 returns 的值 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
变量现在具有有效的内存地址,因此可以安全地取消引用。
第 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);
}
Part 1 和Part 2 有什么区别吗,区别是一个使用**line
,另一个只是*line
。
根据我的理解,两者应该是一样的。
我正在使用它们来测试我自己的函数实现,该函数读取 return 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
变量的值。所以当函数 returns 的值 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
变量现在具有有效的内存地址,因此可以安全地取消引用。