C - Malloc 看起来在我的程序中不起作用



我有一个函数打印文件的整个内容,该函数似乎工作得很好,但valgring抱怨条件跳转或移动取决于未初始化的值未初始化的值是由堆分配:

==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 Existsn", 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))。

字符串必须以空结束。如果没有它,程序会有未定义的行为,valgrind会正确地报告。

以空结束字符串的最简单方法是:

size = fread (buffer,1,length,file); /* no need to specify useless extra char */
                                     /* it will never be read */
...                                  /* check for errors here */
buffer[length] = '';               /* <--- null termination */

calloc用NUL字符填充整个缓冲区,但这是浪费循环。你只需要一个。

通过malloc()获得的内存未初始化。这是故意的。解决方法是使用calloc(),或者在读取之前初始化通过malloc()获得的内存。在某些情况下,你只能初始化它的一部分,通常你有更好的初始值比所有的零可用。

但是,您的特定错误仅与此相关。你通过fread()初始化了大部分缓冲区,但是你分配了比文件长度多一个字节,并且fread()在最后一个字节中不存储任何东西。看起来也许你打算添加一个''终止符,但忘记了。这是valgrind抱怨的最后一个字节。

在这种情况下,calloc()执行的内存清除基本上没有任何作用,因为您将覆盖缓冲区中的所有字节,只保留一个字节。但是它也对最后一个字节进行了初始化,当您无法以其他方式初始化它时,这将为您省去许多麻烦。

相关内容

  • 没有找到相关文章