我有一个包含一些字符串的指针数组(char **)。数组以空字符串('\ 0')结尾。我应该在该字符串数组中搜索特定单词并删除整行(ofc使用realloc并缩短字符串数组)。我很难做到这一点,我一直得到'糟糕的ptr'错误。
我的代码:
void deleteSentence(char **text){
char *word,*fptr;
int i=0;
word=(char*)calloc(BUFFER,sizeof(char));
printf("Enter word to delete sentences:\n");
gets(word);
while(text[i][0]!='\0'){
char *str=(char*)malloc((strlen(text[i])+1)*sizeof(char));
strcpy(str,text[i]);
fptr=strtok(str,DELIM);
while(fptr!=NULL){
if(strcmp(fptr,word)==0){
int j=i;
while(text[j][0]!='\0'){
text[j]=(char*)realloc(text[j],(strlen(text[j+1]))*sizeof(char));
strcpy(text[j],text[j+1]);
j++;
}
free(text[j]);
}
fptr=strtok(NULL,DELIM);
if(fptr!=NULL)
i++;
}
}
}
非常感谢:)
答案 0 :(得分:2)
你正在泄漏记忆,就像筛子漏水,并且至少在两个地方超过你的阵列。此外,输入与此代码的功能目的的集成实际上 nothing 可以提供帮助。该函数应该只做一件事:
给定指向以空字符串(或NULL)结尾的
char*
指针数组的指针,删除指针数组中包含 word 的所有字符串。生成的可能压缩的数组是函数的返回值。
考虑一下:
char ** deleteSentances(char **text, const char *word)
{
char **dst = text, **src = text, **res = text;
size_t size = 1, deleted = 0;
// loop while we have a non-null string that isn't empty
while (*src && (*src)[0])
{
char *tmp = strdup(*src);
if (tmp == NULL)
{
perror("Failed to allocate tmp");
exit(EXIT_FAILURE);
}
char *token = strtok(tmp, DELIM);
// search for matching word
while (token && strcmp(word, token))
token = strtok(NULL, DELIM);
// if not found, keep the string. otherwise delete it.
if (!token)
{
*dst++ = *src++;
size++;
}
else
{
free(*src++);
++deleted;
}
// don't need this.
free(tmp);
}
// resize the original array (which could have only gotten smaller)
if (deleted > 0)
{
res = realloc(text, size * sizeof(*res));
if (res == NULL)
{
perror("Failed to allocate res");
exit(EXIT_FAILURE);
}
res[size-1] = *src;
}
return res;
}
希望这足以解释。代码的调用方式如下:
char **text, *word;
//... populate text with strings
//... populate word with prospect word
text = deleteSentances(text, word);
内存泄漏O'Festival
OP希望了解原始发布算法中内存泄漏的位置。首先考虑以下几点:对于每个分配,应该有一个已知的点,即释放那个记忆。这个例子有点难以说明这个概念,因为你将动态分配带到函数中,并且中的一些将被保留。
尽管如此,请考虑以下景点。我们假设在某种程度上我们分配了这种形式的指针数组:
char **text = malloc(N * sizeof(*text));
即。我们有N
个字符点。在每一个中,我们进一步假设字符串的动态分配也已经发生:
for (int i=0; i<(N-1); ++i)
{
//... compute length of next string
text[i] = malloc(length * sizeof(**text));
//... copy in next string to text[i]
}
最后,text
数组中的最后一个字符指针是NULL或指向长度为0的动态字符串(即0长度终止的字符串)。
呼。好。毕竟,让我们来看看你的算法:
void deleteSentence(char **text)
{
char *word,*fptr;
int i=0;
// Leak 1: allocate a single buffer of BUFFER-length.
// this is never freed anywhere in this function
word=(char*)calloc(BUFFER,sizeof(char));
printf("Enter word to delete sentences:\n");
// Problem: gets() is so evil and bad it has been deprecated from
// the C langage and will not be available in the next release.
// use fgets() instead.
gets(word);
while(text[i][0]!='\0')
{
// Leak 2: Done N times, where N is the number of strings in
// your original array. again, this is never freed.
char *str=(char*)malloc((strlen(text[i])+1)*sizeof(char));
strcpy(str,text[i]);
fptr=strtok(str,DELIM);
while(fptr!=NULL)
{
if(strcmp(fptr,word)==0)
{
int j=i;
while(text[j][0]!='\0')
{
// Leak 3: Done M-N times for ever string we find in position
// M of the original array. This can be *huge* if there are
// a decent number of number of reductions that crunch your
// original array down.
text[j]=(char*)realloc(text[j],(strlen(text[j+1]))*sizeof(char));
strcpy(text[j],text[j+1]);
j++;
}
// Problem: this just freed the termination string, which should
// never be done. We now have undefined behavior for the rest
// of this algorithm since the terminatingg string is invalid.
free(text[j]);
// Problem: You shoud break right here. See below for why
}
// Problem: you're missing an else condition here. At this point
// if the strcmp() found a match there is no reason to continue
// the loop. You found a match and deleted the string, crunching
// all the other string down one slot in a most-inefficient
// memory-leaking algorihm.
fptr=strtok(NULL,DELIM);
// Problem: the logic here is completely wrong. The i in this case
// should be incremented OUTSIDE the inner while loop. Furthermore
// the test is backwards.
if(fptr!=NULL)
i++;
}
}
}
简而言之,如果有可能泄漏