简体   繁体   中英

Why does using a char** cause a segfault where a char* works?

Part 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

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 . 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.

The problem:

Part 1 test works fine. Part 2 testing results in segmentation fault

The implementation of get_next_line() remain same for both.

In the first case using &line passes a valid address to get_next_line . But in the second case, using line passes an uninitialised variable to the function. 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).

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. So there is no way that get_next_line can change the value of the caller's line variable. So when the function returns the value of line is undefined since it was never initialised. 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.

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:

*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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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