首页 > 解决方案 > 条件跳转或移动取决于使用 fread() 后未初始化的值

问题描述

出于某种原因,这个超级简单的代码给了我一个 valgrind 错误。代码摘录:

char* readFile(char* filename){
    FILE * f = fopen (filename, "rb");
    if (f){
        printf("sucessfully opened file\n");
        fseek (f, 0, SEEK_END);
        int length = ftell (f);
        fseek (f, 0, SEEK_SET);
        char* buffer = malloc (length*2);  <- line 109
        if (buffer){
            printf("in here");
            fread (buffer, 1, length, f);
        }
        fclose (f);
        buffer[length+1]='\0';
        printf("buffer: %s",buffer);         <- line 116

瓦尔格林:

==102== Memcheck, a memory error detector
==102== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==102== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==102== Command: ./run
==102==
==102== error calling PR_SET_PTRACER, vgdb might block
inputting file:
sucessfully opened file
==102== Conditional jump or move depends on uninitialised value(s)
==102==    at 0x483EF58: strlen (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==102==    by 0x48CEE94: __vfprintf_internal (vfprintf-internal.c:1688)
==102==    by 0x48B7EBE: printf (printf.c:33)
==102==    by 0x40172C: readFile (functions.c:116)
==102==    by 0x403108: main (functions.c:649)
==102==  Uninitialised value was created by a heap allocation
==102==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==102==    by 0x4016BB: readFile (functions.c:109)
==102==    by 0x403108: main (functions.c:649)
==102==

我的一个较大程序的一部分是这个函数,它读取文件并将其内容存储在缓冲区中。这是程序做的第一件事,所以我在其他地方遇到的错误不应该真正影响这里的行为。帮助将不胜感激。

标签: cvalgrind

解决方案


你有一个错误的错误。您将length字节读入元素buffer[0]...buffer[length-1](从零开始的数组,请记住),因此终止的空字符应该进入buffer[length]. 但是你把它放进去buffer[length+1],所以printf第 116 行试图打印buffer[length]从未被覆盖的垃圾字符。

另一个问题是fread可能会失败,或者读取的字节数少于length字节。如果发生这种情况,剩余的字节buffer不会被覆盖,然后printf将尝试打印未初始化的数据。您需要检查 的返回值fread以查看成功读取了多少字节,如果小于 则做出相应的响应length

最后,如果malloc应该失败,它将设置buffer为 NULL。然后buffer[length+1] = '\0'将取消引用与 null 相关的指针,从而导致未定义的行为。您需要更改逻辑以正确处理malloc返回 NULL,并且buffer在这种情况下不取消引用或打印。


推荐阅读