我的程序有内存泄漏,但我想我找到了原因。我正在做的是使用concat函数将标准输入中的所有单词添加到一个字符串中。
这是一个功能:
Word* readWords(FILE *file) {
char buffer[201];
char* all_words_string = "";
Word* word_node_list = NULL;
char* cp = fgets(buffer, 201, file);
while (cp != NULL) {
all_words_string = concat(all_words_string, cp);
cp = fgets(buffer, 201, file);
}
char** word_list = wordList(all_words_string); //You can probably ignore this
free(all_words_string);
word_node_list = count_words(word_list); //Ignore this
freeWordList(word_list); //Ignore this
free(word_list); //Ignore this
return word_node_list;
}
调用函数concat:
char* concat(char *s1, char *s2){
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
我认为while循环
while (cp != NULL) {
all_words_string = concat(all_words_string, cp);
cp = fgets(buffer, 201, file);
}
负责我的内存泄漏。因为我在concat中分配了所有这些空间,然后删除指向它的指针,然后我只释放它的最后一个实例。
这是我内存泄漏的原因吗?如果是这样,我该如何解决?
答案 0 :(得分:4)
您已正确分析问题。每个malloc()
和calloc()
都应该与相应的free()
配对,而您无法做到。您的代码也有一些其他的不足之处,例如无法检查错误条件的函数结果。
我建议您查看realloc()
,这会显着缓解您的问题。就上述处方而言,它允许您避免在malloc()
之前插入额外的free()
来电。此外,它的行为将允许您在初始化all_words_string
时避免一些轻微的怪异。例如:
Word *readWords(FILE *file) {
char *all_words_string = NULL; /* NULL, not "" */
char *cp;
/* ... */
cp = fgets(buffer, 201, file);
while (cp != NULL) {
all_words_string = concat(all_words_string, cp);
cp = fgets(buffer, 201, file);
}
/* ... */
free(all_words_string);
/* ... */
}
char* concat(char *base, const char *to_add){
/* when its first argument is NULL, realloc() works like malloc(): */
char *result = realloc(base, strlen(base) + strlen(to_add) + 1);
if (result != NULL) { /* realloc() (and malloc()) returns NULL on failure */
/* no need to copy the original string */
/* no need to free it, either */
strcat(result, to_add);
}
return result;
}
答案 1 :(得分:3)
您需要将结果存储在新变量中,以便在分配新值之前释放旧变量。例如:
// Need to allocate an empty string dynamically so we can free it
// later on.
char* all_words_string = malloc(1);
all_word_string[0] = 0;
...
char* tmp = concat(all_words_string, cp);
if (tmp != NULL && tmp != all_words_string) {
free(all_words_string);
all_words_string = tmp;
}
答案 2 :(得分:3)
当您正在寻找内存泄漏时,您需要计算malloc
和free
的数量,并确保它们匹配。
您可能会说在此代码中有一个malloc
和一个free
,这是真的。但是 - 你从循环中调用malloc
。
所以每次你绕过这个循环:
while (cp != NULL) {
all_words_string = concat(all_words_string, cp);
cp = fgets(buffer, 201, file);
}
你打电话给malloc一次。当你弹出循环时,你已经完成了一个未指定数量的malloc(可能为零)并且没有释放。
然后你这样做:
自由(all_words_string);
所以你现在已经完成了1 free
和0,1或者两个或更多malloc
次。
第一个会导致崩溃(因为你正在释放一个不是malloc
的字符串),第二个会很好,第三个会导致内存泄漏。
你需要编写更像这样的代码:
char *all_words_string = strdup("");
...
while (cp != NULL) {
char *tmp = concat(all_words_string, cp);
free(all_words_string);
all_words_string = tmp;
cp = fgets(buffer, 201, file);
}
...
free(all_words_string)
答案 3 :(得分:1)
在进入时似乎每次都会造成泄漏:
char* concat(char *s1, char *s2){
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
不要在这里调用malloc而是考虑调用realloc。 替换下面的行
char * result = malloc(strlen(s1)+ strlen(s2)+1);
与
s1 = realloc(s1,(strlen(s1)+ strlen(s2)+1));
这应该负责动态释放先前分配的内存。