Parsing a string in C with strsep (alternative methods)
Solution 1
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);
Solution 2
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).
Solution 3
The strsep function updates its first argument (so it points right after the token it found). You need to store the value returned by malloc in a separate variable and free this variable.
Kyrol
Computer Science - University of Pisa C and Network engineer at qxip
Updated on August 12, 2022Comments
-
Kyrol almost 2 years
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