Search code examples
cvalgrindrealloc

valgrind reporting "Invalid write of size 8"


I'm trying to track down where valgrind is finding this invalid write of size 8 in some code, but am having a hard time seeing it. I'm sure valgrind is correct, I just don't see it. I've reproduced the original error by stripping out the function and doing the same thing, more or less, with the following code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

double* do_realloc(double* orig_graph, int graph_width, int* graph_allocated)
{
    double *graph = (double *)(realloc(orig_graph, (graph_width + 1) * sizeof(*graph)));
    printf("reallocing graph from %d to %d\n", *graph_allocated, graph_width);
    if (!orig_graph) {
        /* initialize */
        memset(graph, 0, graph_width * sizeof(double));
    } else if (graph) {
        if (graph_width > *graph_allocated) {
            /* initialize the new region */
            printf("old region: %p, new region: %p, offset: %d, length: %d\n", orig_graph, graph,
                 (*graph_allocated * sizeof(double)),
                 (graph_width - *graph_allocated) * sizeof(*graph));
            memset(graph + (*graph_allocated * sizeof(*graph)),
                   0,
                   (graph_width - *graph_allocated) * sizeof(*graph));
        }
    } else {
        printf("reallocing FAILED\n");
        graph = orig_graph;
        graph_width = *graph_allocated;
    }

    *graph_allocated = graph_width;
    return graph;

}

int main()
{
    double* graph = NULL;
    int allocated = 0;

    graph = do_realloc(graph, 307, &allocated);
    graph = do_realloc(graph, 300, &allocated);
    graph = do_realloc(graph, 307, &allocated);

}

And the valgrind output is:

$ valgrind ./t 
==4250== Memcheck, a memory error detector
==4250== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4250== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==4250== Command: ./t
==4250== 
reallocing graph from 0 to 307
reallocing graph from 307 to 300
reallocing graph from 300 to 307
old region: 0x51d4e60, new region: 0x51d5800, offset: 2400, length: 56
==4250== Invalid write of size 8
==4250==    at 0x4C348BE: memset (vg_replace_strmem.c:1094)
==4250==    by 0x4007A9: do_realloc(double*, int, int&) (in /home/dmcbride/tmp/v/t)
==4250==    by 0x400842: main (in /home/dmcbride/tmp/v/t)
==4250==  Address 0x51da300 is 16,672 bytes inside an unallocated block of size 4,185,600 in arena "client"
==4250== 
==4250== Invalid write of size 8
==4250==    at 0x4C348E6: memset (vg_replace_strmem.c:1094)
==4250==    by 0x4007A9: do_realloc(double*, int, int&) (in /home/dmcbride/tmp/v/t)
==4250==    by 0x400842: main (in /home/dmcbride/tmp/v/t)
==4250==  Address 0x51da320 is 16,704 bytes inside an unallocated block of size 4,185,600 in arena "client"
==4250== 
==4250== Invalid write of size 8
==4250==    at 0x4C348F3: memset (vg_replace_strmem.c:1094)
==4250==    by 0x4007A9: do_realloc(double*, int, int&) (in /home/dmcbride/tmp/v/t)
==4250==    by 0x400842: main (in /home/dmcbride/tmp/v/t)
==4250==  Address 0x51da328 is 16,712 bytes inside an unallocated block of size 4,185,600 in arena "client"
==4250== 
==4250== Invalid write of size 8
==4250==    at 0x4C348FD: memset (vg_replace_strmem.c:1094)
==4250==    by 0x4007A9: do_realloc(double*, int, int&) (in /home/dmcbride/tmp/v/t)
==4250==    by 0x400842: main (in /home/dmcbride/tmp/v/t)
==4250==  Address 0x51da330 is 16,720 bytes inside an unallocated block of size 4,185,600 in arena "client"
==4250== 
==4250== 
==4250== HEAP SUMMARY:
==4250==     in use at exit: 2,456 bytes in 1 blocks
==4250==   total heap usage: 4 allocs, 3 frees, 8,336 bytes allocated
==4250== 
==4250== LEAK SUMMARY:
==4250==    definitely lost: 2,456 bytes in 1 blocks
==4250==    indirectly lost: 0 bytes in 0 blocks
==4250==      possibly lost: 0 bytes in 0 blocks
==4250==    still reachable: 0 bytes in 0 blocks
==4250==         suppressed: 0 bytes in 0 blocks
==4250== Rerun with --leak-check=full to see details of leaked memory
==4250== 
==4250== For counts of detected and suppressed errors, rerun with: -v
==4250== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 0 from 0)

The original code has much more than this, but I'm only trying to solve the first problem right now, and will continue investigating other problems after this. I think this is related to the crash that the main application is having right after this point, every single time.

(Someone removed the "C" tag because I had left some C++-isms in, but that seems to me to be missing the purpose, so I removed all C++-isms and got the same results.)


Solution

  • from my analysis of the posted code,

    The problem is in the call to memset() (which goes along with most of the valgrind error messages.)

    Where writing a sizeof(double) beyond the end of the allocated memory area.

    And failing to pass the allocated memory to free() before exiting the program.