0

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.

7
  • char** split_path(char * path, int* count) { Commented May 29, 2016 at 21:45
  • I'll give it a try but I'm not sure why that would make much of a difference. Commented May 29, 2016 at 21:45
  • what @BLUEPIXY said... or use char*** so out actually gets changed and returned. Commented May 29, 2016 at 21:49
  • well that worked, but why? out is a pointer so why wouldn't it get changed? Would I need another level of pointer, like char**? Commented May 29, 2016 at 21:51
  • You aren't accessing the memory allocated in the function. Commented May 29, 2016 at 22:53

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

it works! thank you, I realize now that if I'm wanting to maintain a reference to a 2d array of memory I need a triple pointer, just like if I want a reference to a single int I need an int pointer. Makes sense.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.