繁体   English   中英

malloc看起来无法在我的程序中工作

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM