Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing a string in C with strsep (alternative methods)

I want to parse a string, and I use strsep function:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{

  char str[] = "Marco:Q:2F7PKC";
  char *token1, *token2, *token3;
  char *r = malloc(30);

  strcpy(r, str);

  token1 = strsep(&r, ":");
  token2 = strsep(&r, ":");
  token3 = strsep(&r, ":");

  printf("tok1 = %s\n", token1);
  printf("tok2 = %s\n", token2);
  printf("tok3 = %s\n", token3);

  free(r);

  return 0;

}

The function do its job well, but If I launch valgrind, the allocated string char * r does not freed correctly (definitely lost: 30 bytes in 1 blocks).

I'd like to know why and if there are alternative way to do the same thing, maybe without call strsep.

I call valgrind with valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./a.out

like image 792
Kyrol Avatar asked Jan 27 '14 14:01

Kyrol


2 Answers

strsep overwrites the target of its first (pointer-to-pointer) argument, so you lose the pointer to the malloc'd buffer's base. In fact, if you were do put a printf("%p\n", r); just before the free, you'd find out that you're freeing a null pointer, which has no effect.

The easy solution is to introduce an additional variable to keep that pointer around and free it when you're done. Idiomatic usage would be

char *r = strdup("Marco:Q:3F7PKC");
// check for errors

char *tok = r, *end = r;
while (tok != NULL) {
    strsep(&end, ":");
    puts(tok);
    tok = end;
}

free(r);
like image 130
Fred Foo Avatar answered Sep 27 '22 18:09

Fred Foo


I would like to a bit simplify a good reply from Fred Foo:

char *end, *r, *tok;

r = end = strdup("Marco:Q:3F7PKC");
assert(end != NULL);

while ((tok = strsep(&end, ":")) != NULL) {
    printf("%s\n", tok);
}

free(r);

It gives the same result. But it is worth to say that strsep(3) stores next value after delimiter into end variable and returns current value (into tok variable).

like image 20
jrk Avatar answered Sep 27 '22 19:09

jrk