简体   繁体   中英

Segfault while accessing memory malloc'd in function

I'm trying to write a function that takes in a path (char *) and splits it into an array of strings based around the '/' delimiter. Simplified code below :

int split_path(char * path, char ** out) {
    out = NULL;
    char * token = strtok(path, "/");
    int count = 0;

    while(token) {
        out = realloc(out, sizeof(char*) * (++count));
        out[count-1] = malloc(sizeof(char) * strlen(token)+1);
        strcpy(out[count-1], token);
        fprintf(stderr, "%s\n", out[count-1]);

        token = strtok(NULL, "/");
    }   

    out = realloc(out, sizeof(char*) * (count+1));
    out[count] = NULL;

    return count;
}

int main(int argc, char * argv[]) {
    char path[] = "/home/pirates/are/cool/yeah";

    char ** out;

    int count = split_path(path, out);

    fprintf(stdout, "count: %d\n", count);
    fprintf(stderr, "1st: %s\n", out[0]); // segfaults here
    return 0;
}

All of the print statements in the split_path function print perfectly, the output looks like this :

count: 1, string: home
count: 2, string: pirates
count: 3, string: are
count: 4, string: cool
count: 5, string: yeah
count: 5
1st: ./a.out
[1]    5676 segmentation fault (core dumped)  ./a.out

But for some reason when I get back to the main function the double-char-array is no longer valid. I thought that it might be because it was pointing to memory declared in that split_path function but I'm doing strcpy to get the strings into it so it shouldn't be pointing back to memory that is local to that function. Any help is greatly appreciated.

You are mismanaged the out parameter. The out variable in main() is never assigned a valid memory address, thus the segfault. The out parameter in split_path() never updates the out variable in main() . You need to pass the address of the variable to split_path() so it can update the variable, and access the memory that the variable points to.

Also note that strtok() modifies the string it is parsing, so you should make a copy and then parse the copy so the original does not get destroyed. Otherwise, consider using strchr() instead of strtok() .

Try something more like this instead:

int split_path(char * path, char *** out) {
    *out = NULL;
    char * tmp = strdup(path);
    if (!tmp) { ... }
    char * token = strtok(tmp, "/"');
    int count = 0;
    char ** newout;

    while (token) {
        newout = realloc(*out, sizeof(char**) * (++count));
        if (!newout) { ... }
        *out = newout;
        (*out)[count-1] = malloc(sizeof(char) * (strlen(token)+1));
        if (!(*out)[count-1]) { ... }
        strcpy((*out)[count-1], token);
        fprintf(stderr, "%s\n", token);

        token = strtok(NULL, "/");
    }   

    newout = realloc(*out, sizeof(char**) * (count+1));
    if (!newout) { ... }
    *out = newout;
    (*out)[count] = NULL;

    free (tmp);
    return count;
}

int main(int argc, char * argv[]) {
    char path[] = "/home/pirates/are/cool/yeah";

    char ** out;

    int count = split_path(path, &out);

    fprintf(stdout, "count: %d\n", count);
    fprintf(stderr, "1st: %s\n", out[0]); // segfaults here

    free (out);
    return 0;
}

And don't forget error handling. I've left it out of this example for brevity, but you should not leave it out of your real code.

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