我想解析一个字符串,并使用strsep
函数:
#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;
}
该函数可以正常工作,但是如果我启动 valgrind ,分配的字符串char * r
就无法正确释放(肯定丢失:1个块中30个字节)。
我想知道为什么以及是否有其他方法可以做同样的事情,也许没有电话 strsep 。
我用valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./a.out
答案 0 :(得分:15)
strsep
会覆盖其第一个(指针指向)参数的目标,因此您将失去指向malloc
'缓冲区基础的指针。事实上,如果你确实在printf("%p\n", r);
之前放了一个free
,你就会发现你正在释放一个无效的空指针。
简单的解决方案是引入一个额外的变量,以便在完成后保持指针和free
。习惯用法是
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);
答案 1 :(得分:3)
我想稍微简化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);
它给出了相同的结果。但值得一提的是,strsep(3)
将分隔符存储到end
变量后存储下一个值,并返回当前值(进入tok
变量)。
答案 2 :(得分:1)
strsep函数更新其第一个参数(因此它指向它找到的标记之后)。您需要将malloc返回的值存储在单独的变量中并释放此变量。