【发布时间】:2016-07-21 23:47:44
【问题描述】:
在我修复了内存泄漏之后,valgrind 向我显示了一堆如下的行错误,我不知道如何修复它。是因为我释放的空间比我需要的多吗?
第 39 行:
root = importTree(*(argv+1));
第 72 行:
printf("Result found for %d:\n city: %s\n state:%s\n", zip, new->city, new->state);
Node *importTree(char *filename) {
Node *root = NULL;
FILE *fp = fopen(filename, "r");
if (!fp) {
printf("Error opening file.\n");
return NULL;
}
while (!feof(fp)) {
Node *new = malloc(sizeof(Node));
if (!new) {
printf("Failed to allocate memory. Ending read.\n");
exit(1);
fclose(fp);
}
new->city = malloc(sizeof(char) * MAXCITYNAME);
if (!(new->city)) {
printf("Failed to allocate memory. Ending read.\n");
exit(1);
fclose(fp);
}
new->left = NULL;
new->right = NULL;
char *line = malloc(sizeof(char) * MAXLINELENGTH);
if (!line) {
printf("Failed to allocate memory. Ending read.\n");
exit(1);
fclose(fp);
}
if (fgets(line, MAXLINELENGTH, fp) == NULL) {
if (!feof(fp)) {
printf("File reading ended prematurely. Check for errors in the file.\n");
exit(1);
fclose(fp);
}
free(new->city);
free(line);
free(new);
fclose(fp);
break;
}
char *tmp = strtok(line, ",");
new->zipCode = atoi(tmp);
tmp = strtok(NULL, ",");
strcpy(new->city, tmp);
new->city[strlen(tmp) + 1] = '\0';
tmp = strtok(NULL, ",");
strcpy(new->state, tmp);
new->state[2] = '\0';
root = addNode(root, new);
if (!root) {
printf("Root of tree is still NULL! Ending read.\n");
exit(1);
}
free(line);
free(new->city); \\this is the line 220
}
fclose(fp);
return root;
}
这是 valgrind 的输出:
Invalid read of size 1
==7879== at 0x517FAB4: vfprintf (vfprintf.c:1635)
==7879== by 0x5188C98: printf (printf.c:34)
==7879== by 0x400BBD: main (hw3.c:72)
==7879== Address 0x5657a30 is 0 bytes inside a block of size 30 free'd
==7879== at 0x4C2AD17: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==7879== by 0x40103F: importTree (hw3.c:220)
==7879== by 0x400A31: main (hw3.c:39)
==7879==
==7879== Invalid read of size 1
==7879== at 0x51ADA99: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1342)
==7879== by 0x517FA6C: vfprintf (vfprintf.c:1635)
==7879== by 0x5188C98: printf (printf.c:34)
==7879== by 0x400BBD: main (hw3.c:72)
==7879== Address 0x5657a37 is 7 bytes inside a block of size 30 free'd
==7879== at 0x4C2AD17: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==7879== by 0x40103F: importTree (hw3.c:220)
==7879== by 0x400A31: main (hw3.c:39)
==7879==
==7879== Invalid read of size 1
==7879== at 0x51ADAAC: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1342)
==7879== by 0x517FA6C: vfprintf (vfprintf.c:1635)
==7879== by 0x5188C98: printf (printf.c:34)
==7879== by 0x400BBD: main (hw3.c:72)
==7879== Address 0x5657a36 is 6 bytes inside a block of size 30 free'd
【问题讨论】:
-
不要使用
sizeof(char),它与 1 没有什么不同。所以它是多余的,只会使代码更难阅读,并且看起来比必要的行长。而且你确实不需要malloc(),因为MAXLINESIZE使用数组,malloc()很慢,你真的不需要它。并且测试文件结尾也是多余的,您已经检查了fgets()是否返回NULL。 -
Also
while (!feof(file))is always wrong。您也可以fclose()该文件两次。在明显担心 valgrind 之前,您需要检查很多事情。 -
@chqrlie:谢谢你添加空格,代码真的让我很难过。
-
哦,
fclose(file)在exit(1)之后根本不起作用。你知道exit(1)会做什么吗? -
@iharob:不,它不会使代码更难阅读。数组分配的公认习语是
malloc(N * sizeof element)。每次分配数组时都遵循它,即使您知道sizeof element保证为 1。偏离此模式会使代码更难阅读,因为它会使读者绊倒并花时间找出为什么省略sizeof element.虽然很容易弄清楚,但它仍然无关紧要,不值得花时间。
标签: c memory-leaks valgrind