【问题标题】:Why does using a char** cause a segfault where a char* works?为什么使用 char** 会导致 char* 工作的段错误?
【发布时间】:2019-11-24 21:42:47
【问题描述】:

第 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() 的实现对两者保持相同。

【问题讨论】:

  • 显示get_next_line()的定义
  • 在第二种情况下,line 是一个未初始化的值。您没有显示get_next_line,但我认为它需要一个有效的指针而不是未初始化的指针。也就是说,第一种情况下的&line 是有效地址,而第二种情况下的line 具有未定义的值。

标签: c pointers double-pointer


【解决方案1】:

在第一种情况下,使用&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 没有取消引用lineprintf 仍然会导致未定义的行为,因为它取消引用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 变量现在有一个有效的内存地址,因此可以安全地取消引用。

【讨论】:

    猜你喜欢
    • 2011-02-23
    • 2015-07-29
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2015-09-06
    相关资源
    最近更新 更多