我有一个函数,它接受一个字符串并将其拆分为标记,因为我想返回这些标记,我使用malloc分配一个变量。
<div>
<span>
<tr>
<span class="test">
<p>Foo</p>
</span>
</tr>
<div>
<tr>
<li>
<p>Bar</p>
</li>
</tr>
</div>
<p>FooBar</p>
</span>
</div>
我尝试用另一个函数释放这个表:
char** analyze(char* buffer)
{
int i= 0;
char* token[512];
char** final = (char**)malloc(strlen(buffer)+1);
if ( final == NULL ) { perror("Failed to malloc"); exit(10); }
token[i] = strtok(buffer, " ");
while( token[i] != NULL )
{
final[i] = malloc(strlen(token[i])+1);
if( final[i] == NULL ) { perror("Failed to malloc"); exit(11); }
final[i] = token[i];
i++;
token[i] = strtok(NULL, " ");
}
final[i] = malloc(sizeof(char));
if( final[i] == NULL ) { perror("Failed to malloc"); exit(12); }
final[i] = NULL;
return final;
}
主要使用:
void free_table(char** job)
{
int i = 0;
while( job[i] != NULL )
{
free(job[i]);
i++;
}
free(job[i]); //free the last
free(job);
}
和
char** job = analyze(buffer); // buffer contains the string
当我尝试释放表格时,我收到此错误:
free_table(job);
并且错误继续......
我做错了什么?
答案 0 :(得分:1)
首先:
char** final = (char**)malloc(strlen(buffer)+1);
这会分配strlen(buffer) + 1
字节 ,而不是&#34;元素&#34;的数量。由于sizeof(char*)
很可能比单个字节大得多,所以你可能会在这里分配很少的内存。
由于您不知道可能有多少令牌,因此您不应分配固定金额,而是根据需要使用realloc
重新分配。
然后是第二个问题:
final[i] = malloc(strlen(token[i])+1);
...
final[i] = token[i];
在第一个语句中,为token[i]
指向的字符串分配足够的内存,并将指向该内存的指针分配给final[i]
。 但是 然后你立即重新分配 final[i]
指向其他地方,一些你从{{1}获得的记忆}}。你应该copy the string而不是重新分配指针:
malloc
在一个不相关的注释中,strcpy(final[i], token[i]);
不需要成为指针数组。它可以只是一个指针:
token
可能的实施示例:
char *token = strtok(...);
请注意char **analyze(char *buffer)
{
size_t current_token_index = 0;
char **tokens = NULL;
// Get the first "token"
char *current_token = strtok(buffer, " ");
while (current_token != NULL)
{
// (Re)allocate memory for the tokens array
char **temp = realloc(tokens, sizeof *temp * (current_token_index + 1));
if (temp == NULL)
{
// TODO: Better error handling
// (like freeing the tokens already allocated)
return NULL;
}
tokens = temp;
// Allocate memory for the "token" and copy it
tokens[current_token_index++] = strdup(current_token);
// Get the next "token"
current_token = strtok(NULL, " ");
}
// Final reallocation to make sure there is a terminating null pointer
char **temp = realloc(tokens, sizeof *temp * (current_token_index + 1));
if (temp == NULL)
{
// TODO: Better error handling
// (like freeing the tokens already allocated)
return NULL;
}
tokens = temp;
// Terminate the array
tokens[current_token_index] = NULL;
return tokens;
}
不是标准的C函数,但它足以让它假设它存在。在它不存在的不太可能的情况下,它很容易实现。