2

I've written the following C function to split a string in a delimiter and return the word number "num_words":

void split_string(char *string, char **result, char *delimiter, int num_words){

    long unsigned int cont_len = strlen(string);
    char line[cont_len];
    strcpy(line, string);

    int i = 0;
    char *tmp;
    char *p = strtok (line, delimiter);

    while ((p != NULL) & (i <= num_words)){
        if (i == num_words){
            *result = strdup(p);
            break;
        }
        p = strtok (NULL, delimiter);
        i = i+1;
    }
    free(p);
}

and in main:

char *string = "hello whole world";
char *result;
char *delimiter = " ";
int   num_words = 2;

split_string(string, &result, delimiter, num_words);

In this example, split_string would make result equal to "world". However, when I try to debug with gdb, I get a munmap_chunk(): invalid pointer error originated in the free(p) code line of the split_string function.

I know that strdup allocates memory, and that's why I was trying to free the p pointer. Where should I place this free? Should I only free(result) in the main instead? I've read answers on similar stackoverflow questions, but none could solve my problem...

imll
  • 321
  • 3
  • 13
  • You did not allocate any data (`strtok()` does not do so), so you must not attempt to free any. The `free()` function is only for releasing dynamically-allocated memory, generally obtained via `malloc` / `calloc` / `realloc`. – John Bollinger Jan 04 '20 at 19:05
  • I didn't say it was `strtok` that allocated memory, but `strdup`, which does allocate memory – imll Jan 04 '20 at 19:07
  • Sorry, I worded that poorly. The pointer value passed to `free()` must either be null or be equal to one previously obtained from an allocation function, and not subsequently freed. At the point where you try to free it, `p` typically does not meet the latter criterion, even when `string` *is* such a pointer at entry to the function. `strdup()` does not factor into it, because at no point does `p` take the return value of a call to `strdup()` as its value. The values of `p` are all return values of `strtok()`. – John Bollinger Jan 04 '20 at 19:14
  • Ok, I think I understand now. So I would only need to `free(result)` in the main? Also, if I remove the `free(p)` from the `split_string` function, will it be free from memory leaks? As it is right now – imll Jan 04 '20 at 19:18
  • 1
    Yes, the caller of `split_string()` needs to take responsibility for freeing the pointer returned via the `result` argument. If `split_string` freed that pointer itself then the caller could not use it. The program will be free of leaks with respect to this particular function if it consistently frees the result pointer obtained from each call. The function should not attempt to `free(p)` at any point. – John Bollinger Jan 04 '20 at 19:24

1 Answers1

0

You don't need to free the memory after strtok.

For further reading: Do I need to free the strtok resulting string?

lory9894
  • 63
  • 5