在malloced字符串上使用strtok有什么我应该知道的吗?
在我的代码中,我(一般而言)
char* line=getline();
Parse(dest,line);
free(line);
其中getline()
是一个将char *返回给某些malloced内存的函数。
Parse(dest, line)
是一个在线解析的函数,将结果存储在dest
中(之前已经部分填充了其他信息)。
Parse()
在线调用strtok()
可变次数,并进行一些验证。
每个标记(指向strtok()
返回的内容的指针)都被放入队列中,直到我知道我有多少。
然后将它们复制到dest。
中的malloc'd char **上现在free(line)
以及一个释放char * []在dest中的每个部分的函数,它们都出现在valgrind上:
“地址0x5179450是38块空闲块中的8个字节”
或类似的东西。
我正在考虑重构我的代码而不是直接将标记存储在char **上,而是存储它们的副本(通过mallocing space == to strlen(token)+1,然后使用strcpy()
)。
答案 0 :(得分:2)
然后将它们复制到dest中的malloc'd char **。
复制字符串,还是复制指针? strtok
函数修改你给它的字符串,这样它就可以指向同一个字符串而不复制任何东西。当你从它获得令牌时,你必须复制它们。只要在使用任何令牌指针的情况下保持输入字符串就可以。
许多人建议您完全避免使用strtok
,因为它容易出错。此外,如果您正在使用线程并且CRT不支持线程,strtok
可能会导致您的应用崩溃。
答案 1 :(得分:2)
有一个函数strdup
,它分配内存然后将另一个字符串复制到其中。
答案 2 :(得分:2)
你问:
有什么我应该知道的 在malloced字符串上使用strtok?
有许多事情需要注意。首先,strtok()
在处理字符串时修改字符串,在找到分隔符的位置插入空值('\0'
)。这不是分配内存的问题(可以修改!);如果您尝试将常量字符串传递给strtok()
,则会出现问题。
其次,您必须像free()
和malloc()
那样拨打calloc()
的电话号码(但realloc()
可能会导致计数混乱)。
在我的代码中,我(一般而言)
char* line=getline(); Parse(dest,line); free(line);
除非Parse()
分配它保留的空间,否则在调用{后dest
结构(或更确切地说,指向dest
结构内的行的指针)时,不能使用free()
结构{1}}。 free()
释放由getline()
分配的空间,并且在此之后使用指针会产生未定义的行为。请注意,未定义的行为包括“看似工作,但只是巧合”的选项。
其中getline()是一个函数 将char *返回给某些malloced 内存和Parse(dest,line)是一个 在线解析的功能, 将结果存储在dest(其中 已经部分填补了, 来自其他信息)。
Parse()调用strtok()一个变量 在线的次数,并做一些 验证。每个令牌(指向 将strtok()返回的内容放入 进入队列直到我知道我有多少 有
请注意,strtok()
返回的指针都是指向由getline()
分配的单个空间块的指针。您尚未描述任何额外的内存分配。
然后将它们复制到malloc'd上 char ** in dest。
这听起来好像是将指针从strtok()
复制到一个指针数组中,但是你没有注意复制这些指针所指向的数据。
现在free(line)和一个函数 free是char * []的每个部分 DEST, 两人都出现在valgrind上:
"Address 0x5179450 is 8 bytes inside a block of size 38 free'd"
或类似的东西。
free()
的'char *[]
'部分的第一个dest
可能有一个指向line
的指针,因此可以释放整个内存块。 dest
部分的所有后续释放都试图释放malloc()
未归还的地址,而valgrind
正试图告诉您。然后free(line)
操作失败,因为free()
中指针的第一个dest
已经释放了该空格。
我正在考虑重构我的代码 [存储] [...]的副本。
提议的重构可能是明智的;其他人已经提到过的功能strdup()
将能够整齐可靠地完成工作。
请注意,重构后,您仍需要释放行,但不会释放strtok()
返回的任何指针。它们只是指向由line
管理的空间的指针,并且在您释放line
时将全部释放。
请注意,您需要释放每个单独分配的(strdup()
'd)字符串以及通过dest
访问的字符指针数组。
或者,请勿在致电Parse()
后立即免费拨打电话。让dest
记录分配的指针(line
),并在释放指针数组时释放它。但是,您仍然不会释放strtok()
返回的指针。
答案 3 :(得分:0)
1,strtok()只在每个匹配的位置写'\ 0'。实际上这一步并不特别。使用strtok()很容易。当然它不能用在只读内存缓冲区上。
对于在parse()中获取的每个子字符串,2,相应地将其复制到malloc()ed缓冲区。如果我给出一个存储子字符串的简单示例,它看起来像下面的代码,从概念上说,虽然它可能与您的实际代码不完全相同:
char **dest; dest = (char**)malloc(N * sizeof(char*)); for (i: 0..N-1) { dest[i] = (char*)malloc(LEN); strcpy(dest[i], sub_strings[i]); NOTE: above 2 lines could be just one line as below dest[i] = strdup(sub_string[i]); }
3 free dest,在概念上再次:
for (i: 0..N-1) { free(dest[i]); } free(dest);
4免费电话(线路)也没什么特别的,它也不会影响你的“目标”。
“dest”和“line”使用不同的内存缓冲区,因此如果愿意,您可以在步骤3之前执行步骤4。如果您按照上述步骤操作,则不会发生任何错误。好像你在代码的第2步中犯了错误。