0
votes

The following code, when built on ubuntu creates an executable.

#include <stdio.h>

void otherfunc(FILE* fout){
    fclose(fout);//Line 4
    fout = fopen("test.txt", "w");//Delete contents and create a new file//Line 5
    setbuf(fout, 0);//Line 6
}

int main() {
    FILE *fout = fopen("test.txt", "r");//Line 10
    if (fout) {
        //file exists and can be opened
        fclose(fout);//Line 13
        fout = fopen("test.txt", "a");//Line 14
        setbuf(fout, 0);
    }
    else {
        //file doesn't exists or cannot be opened 
        fout = fopen("test.txt", "a");//Line 19
    }
    
    otherfunc(fout);//Line 22
    
    fclose(fout);//Line 24
    return 0;
}

When run through valgrind, valgrind gives the following warnings:

==13569== Invalid read of size 4

==13569== at 0x4EA7264: fclose@@GLIBC_2.2.5 (iofclose.c:53)

==13569== by 0x400673: main (newmain.cpp:24)

==13569== Address 0x52042b0 is 0 bytes inside a block of size 552 free'd

==13569== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==13569== by 0x4EA7362: fclose@@GLIBC_2.2.5 (iofclose.c:84)

==13569== by 0x4005CD: otherfunc(_IO_FILE*) (newmain.cpp:4)

==13569== by 0x400667: main (newmain.cpp:22)

==13569== Block was alloc'd at

==13569== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==13569== by 0x4EA7CDC: __fopen_internal (iofopen.c:69)

==13569== by 0x400657: main (newmain.cpp:19)

Essentially, it is complaining that the fclose(fout); on Line 24 is closing an already freed memory that was freed on line 4 fclose(fout); within otherfunc(). But the Line 24's fclose(fout); is meant to close the fopen() performed on Line 5.

At any point in time in the code, whenever a fclose() is called, there is always exactly one open fopen(). Why is this then an invalid read as reported by valgrind?

1

1 Answers

5
votes

otherfunc takes a file pointer by value. So the value you've assigned at line 5 is lost after returning from otherfunc and when it returns into main the value of fout there remains unchanged. It contains a dangling file pointer value that you've closed at line 4. Therefore a call to close on line 24 will receive an invalid pointer.