简体   繁体   English

为什么使用 char** 会导致 char* 起作用的段错误?

[英]Why does using a char** cause a segfault where a char* works?

Part 1第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);
}

Part 2第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);
}

Is there any difference between Part 1 and Part 2, the difference between them is one use **line and another just *line . Part 1 和 Part 2 之间有什么区别吗,它们之间的区别是一个使用**line ,另一个只是*line From my understanding, both should be the same.根据我的理解,两者应该是一样的。

I am using them to test my own implementation of a function that reads and return 1 line.我正在使用它们来测试我自己的读取和返回 1 行函数的实现。

The problem:问题:

Part 1 test works fine.第 1 部分测试工作正常。 Part 2 testing results in segmentation fault第 2 部分测试结果出现分段错误

The implementation of get_next_line() remain same for both. get_next_line()的实现对get_next_line()保持相同。

In the first case using &line passes a valid address to get_next_line .在第一种情况下,使用&line将有效地址传递给get_next_line But in the second case, using line passes an uninitialised variable to the function.但在第二种情况下,使用line将一个未初始化的变量传递给函数。 You didn't show get_next_line but I assume it does something like *line = blah which of course will seg fault if the passed in line value is not a valid address (technically it's undefined behaviour to dereference an uninitialised pointer so it's likely to seg fault but may also exhibit any other behaviour).您没有显示get_next_line但我认为它执行了类似*line = blah ,如果传入的line值不是有效地址,当然会出现段错误(从技术上讲,取消引用未初始化的指针是未定义的行为,因此很可能会出现段错误但也可能表现出任何其他行为)。

Another way to look at it:另一种看待它的方式:

char            **line;
get_next_line(fd, line);
printf("%i-%s\n",i, *line);

That is essentially what the second case does.这基本上就是第二种情况的作用。 We know in C that function arguments are passed by value.我们知道在 C 中函数参数是按值传递的。 So there is no way that get_next_line can change the value of the caller's line variable.所以get_next_line无法改变调用者line变量的值。 So when the function returns the value of line is undefined since it was never initialised.所以当函数返回line的值是 undefined 因为它从未被初始化。 So even if get_next_line does not dereference line the printf will still cause undefined behaviour as it dereferences line but it's value is clearly undefined at that point.因此,即使get_next_line没有取消引用lineprintf仍然会导致未定义的行为,因为它取消引用了line但此时它的值显然是未定义的。

Compare that to the first case where the equivalent opertations are:将其与等效操作为的第一种情况进行比较:

char            *line;
get_next_line(fd, &line);
printf("%i-%s\n",i, *line);

In this case, get_next_line is able to validly change the caller's line variable with something like:在这种情况下, get_next_line能够使用以下内容有效地更改调用者的line变量:

*line = malloc(MY_MAX_LINE_LENGTH);

So when the function exits the caller's line variable now has a valid memory address and hence can be safely dereferenced.所以当函数退出时,调用者的line变量现在有一个有效的内存地址,因此可以安全地取消引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM