[英]malloc doesn't look to work in my program
我有一个函数可以打印文件的全部内容,并且该函数似乎可以正常工作,但是流浪抱怨条件跳转或移动取决于未初始化的值 ,而未初始化的值是由堆分配创建的 :
==7876== Memcheck, a memory error detector ==7876== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==7876== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==7876== Command: ./program ==7876== ==7876== Conditional jump or move depends on uninitialised value(s) ==7876== at 0x4E864B2: vfprintf (vfprintf.c:1642) ==7876== by 0x4E8CC38: printf (printf.c:33) ==7876== by 0x40074C: main (program.c:45) ==7876== Uninitialised value was created by a heap allocation ==7876== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7876== by 0x4008A7: printFile (program.c:23) ==7876== by 0x40073A: main (program.c:43) ==7876== The world is not enought and michi is the only one who's not agree. ==7876== ==7876== HEAP SUMMARY: ==7876== in use at exit: 0 bytes in 0 blocks ==7876== total heap usage: 2 allocs, 2 frees, 621 bytes allocated ==7876== ==7876== All heap blocks were freed -- no leaks are possible ==7876== ==7876== For counts of detected and suppressed errors, rerun with: -v ==7876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
这是程序:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *printFile(char *fileName){
size_t length=0,size=0;
char *buffer;
FILE *file;
file = fopen (fileName , "r" );
if (file==NULL){
printf("\n");
printf("\tThe file %s does not Exists\n", fileName);
exit(1);
}
fseek (file , 0 , SEEK_END);
length = (size_t)ftell (file);
fseek (file , 0 , SEEK_SET);
buffer = malloc(length+1);
if (!buffer){
fputs ("Memory error",stderr);
exit (2);
}
size = fread (buffer,1,length+1,file);
if (size != length){
fputs ("Reading error",stderr);
exit(3);
}
fclose (file);
return buffer;
}
int main (void) {
char *fileName = "test.txt";
char *fileContent = printFile(fileName);
printf("%s",fileContent);
free(fileContent);
return 0;
}
一个快速的解决方法是使用calloc而不是malloc,因为它将返回的字节清零,所以我替换了:
buffer = malloc(length+1);
有:
buffer = calloc(length,sizeof(char*));
valgrind没有抱怨:
==7897== Memcheck, a memory error detector ==7897== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==7897== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==7897== Command: ./program ==7897== The world is not enought and michi is the only one who's not agree. ==7897== ==7897== HEAP SUMMARY: ==7897== in use at exit: 0 bytes in 0 blocks ==7897== total heap usage: 2 allocs, 2 frees, 1,096 bytes allocated ==7897== ==7897== All heap blocks were freed -- no leaks are possible ==7897== ==7897== For counts of detected and suppressed errors, rerun with: -v ==7897== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我的问题是,为什么malloc会产生该错误,以及如何避免出现calloc。 我在这里有一些编码问题还是仅仅是malloc? 。 。 编辑:如果我更改:
size = fread (buffer,1,length+1,file);
有:
size = fread (buffer,1,length,file);
我得到:
==7985== Memcheck, a memory error detector ==7985== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==7985== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==7985== Command: ./program ==7985== ==7985== Invalid read of size 1 ==7985== at 0x4E864B2: vfprintf (vfprintf.c:1642) ==7985== by 0x4E8CC38: printf (printf.c:33) ==7985== by 0x40074C: main (program.c:44) ==7985== Address 0x52022f4 is 0 bytes after a block of size 68 alloc'd ==7985== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7985== by 0x4008A6: printFile (program.c:22) ==7985== by 0x40073A: main (program.c:42) ==7985== The world is not enought and michi is the only one who's not agree. ==7985== ==7985== HEAP SUMMARY: ==7985== in use at exit: 0 bytes in 0 blocks ==7985== total heap usage: 2 allocs, 2 frees, 620 bytes allocated ==7985== ==7985== All heap blocks were freed -- no leaks are possible ==7985== ==7985== For counts of detected and suppressed errors, rerun with: -v ==7985== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
您将读取到缓冲区中的文件内容打印出来,但是没有什么可以确保缓冲区中包含NUL字符,因此valgrind会抱怨,因为printf会解析您的数据直到NUL( jump or move depends on uninitialised value(s)
)。 使用calloc告诉valgrind您要更加谨慎...
通过malloc()
获得的malloc()
未初始化。 那是故意的。 解决方法是改用calloc()
或初始化从malloc()
获得的malloc()
然后再从中读取。 在某些情况下,您只能初始化其中的一部分,并且通常您拥有比全零更好的初始值。
但是,您的特定错误仅与此相关。 您确实通过fread()
初始化了大多数缓冲区,但是分配的字节数比文件长的多,并且fread()
在最后一个字节中不存储任何内容。 似乎您打算添加'\\0'
终止符,但忘记了。 valgrind抱怨的是最后一个字节。
在这种情况下,由calloc()
执行的内存清除几乎没有用,因为您将要覆盖缓冲区中的所有字节,但只能覆盖一个。 但是它也确实初始化了最后一个字节,当您以其他方式无法初始化它时,原来可以为您节省多种麻烦。
您的字符串必须为NUL终止。 没有它,该程序将具有不确定的行为,valgrind会正确报告该行为。
NUL终止字符串的最简单方法是:
size = fread (buffer,1,length,file); /* no need to specify useless extra char */
/* it will never be read */
... /* check for errors here */
buffer[length] = '\0'; /* <--- null termination */
calloc
使用NUL字符填充整个缓冲区,但这是浪费循环的。 您只需要一个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.