free(): invalid next size (normal) on fclose. But

2020-07-25 23:47发布

问题:

The code below breaks on the fclose() call.

void output_gauss_transform(char* filename, char* mode, double** T, 
                            double shift, int len)
{
    FILE* fp;

    printf("Outputting gauss transform to %s.\n", filename);

    if ((fp = fopen(filename, mode)) == NULL){
    perror("Could not open file");
    return;
    }

    int i;

    for (i = 0; i < len; ++i) {
    fprintf(fp, "%lf %lf\n", T[0][i], T[1][i] + shift);
    }

    if (fclose(fp)){
    printf("error closing\n");
    }
}

glibc gives me this error, along with the memory map.

*** glibc detected *** [sourcedir]/.libs/lt-launcher: free(): invalid next size (normal): 0x0821da38 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb739dee2]
/lib/i386-linux-gnu/libc.so.6(fclose+0x154)[0xb738d424]
/src/.libs/libfile_util.so.0(output_gauss_transform+0xa9)[0xb77b5859]
/src/.libs/lt-launcher[0x804a0f9]
/src/.libs/lt-launcher[0x804a2a5]
/src/.libs/lt-launcher[0x804983b]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb73414d3]
/src/.libs/lt-launcher[0x8049915]

When attempting to debug this with valgrind, I get no errors whatsoever, with it outputting the following. What is going on?

==30396== HEAP SUMMARY:
==30396==     in use at exit: 0 bytes in 0 blocks
==30396==   total heap usage: 1,059 allocs, 1,059 frees, 78,149 bytes allocated
==30396== 
==30396== All heap blocks were freed -- no leaks are possible
==30396== 
==30396== For counts of detected and suppressed errors, rerun with: -v
==30396== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

edit: Running valgrind with -v, I get this thing at the end. Perhaps it has something to do with what is going on?

 --31325-- REDIR: 0x454cac0 (operator delete(void*)) redirected to 0x402bb98 (operator delete(void*))

回答1:

This code is the victim, you need to find the perpetrator. When you call fclose, some structure is freed. At that point, the code discovers that the free pool is corrupt and reports an error. However, it's some other chunk of code that corrupted the free pool, not this code.

The most common causes of this error are freeing the same block of memory twice and accessing a block of memory after you've freed it. It's strange that valgrind wasn't able to catch this, since these are exactly the kind of errors it usually catches.