简体   繁体   English

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

[英]malloc doesn't look to work in my program

I have a function which prints the whole content of the file and the function seems to work fine, but valgring complains about Conditional jump or move depends on uninitialised value(s) and Uninitialised value was created by a heap allocation : 我有一个函数可以打印文件的全部内容,并且该函数似乎可以正常工作,但是流浪抱怨条件跳转或移动取决于未初始化的值 ,而未初始化的值是由堆分配创建的

 ==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) 

Here is the program: 这是程序:

#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;
}

A quick fix is to use calloc instead of malloc, because it zeros the returned bytes So I replaced: 一个快速的解决方法是使用calloc而不是malloc,因为它将返回的字节清零,所以我替换了:

buffer = malloc(length+1);

with: 有:

buffer = calloc(length,sizeof(char*));

And valgrind doesn't complain: 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) 

My question is, why does malloc produce that error and how to avoid calloc. 我的问题是,为什么malloc会产生该错误,以及如何避免出现calloc。 Do I have some codding problem here or is just malloc? 我在这里有一些编码问题还是仅仅是malloc? . . EDIT: if I change: 编辑:如果我更改:

size = fread (buffer,1,length+1,file);

with: 有:

size = fread (buffer,1,length,file);

I get: 我得到:

 ==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) 

You print the file content read into your buffer but nothing can ensure that the buffer contains a NUL char, so valgrind complains because printf parse your data until NUL ( jump or move depends on uninitialised value(s) ). 您将读取到缓冲区中的文件内容打印出来,但是没有什么可以确保缓冲区中包含NUL字符,因此valgrind会抱怨,因为printf会解析您的数据直到NUL( jump or move depends on uninitialised value(s) )。 Using calloc tells valgrind that you are more precautious... 使用calloc告诉valgrind您要更加谨慎...

Memory obtained via malloc() is uninitialized. 通过malloc()获得的malloc()未初始化。 That's intentional. 那是故意的。 The workarounds are to use calloc() instead or to initialize that memory obtained via malloc() before you read from it. 解决方法是改用calloc()或初始化从malloc()获得的malloc()然后再从中读取。 Under some circumstances you can initialize only part of it, and often you have better initial values available than all zeroes. 在某些情况下,您只能初始化其中的一部分,并且通常您拥有比全零更好的初始值。

Your particular error is only peripherally related to that, however. 但是,您的特定错误仅与此相关。 You do initialize most of the buffer, via fread() , but you allocate one more byte than the file is long, and fread() does not store anything in that last byte. 确实通过fread()初始化了大多数缓冲区,但是分配的字节数比文件长的多,并且fread()在最后一个字节中不存储任何内容。 It looks like maybe you intended to add a '\\0' terminator, but forgot. 似乎您打算添加'\\0'终止符,但忘记了。 It's that last byte that valgrind complains about. valgrind抱怨的是最后一个字节。

In this case, the memory-clearing performed by calloc() mostly serves no purpose, as you are about to overwrite all bytes in the buffer but one. 在这种情况下,由calloc()执行的内存清除几乎没有用,因为您将要覆盖缓冲区中的所有字节,但只能覆盖一个。 But it does initialize that last byte, too, which turns out to save you several kinds of trouble when you fail to initialize it any other way. 但是它也确实初始化了最后一个字节,当您以其他方式无法初始化它时,原来可以为您节省多种麻烦。

Your string must be NUL-terminated. 您的字符串必须为NUL终止。 Without it, the program has undefined behaviour, which valgrind rightfully reports. 没有它,该程序将具有不确定的行为,valgrind会正确报告该行为。

The easiest way to NUL-terminate the string is: 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 fills the entire buffer with NUL characters, but it's a waste of cycles. calloc使用NUL字符填充整个缓冲区,但这是浪费循环的。 You only need one. 您只需要一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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