0
votes

I am getting a bus error in a huge application that I have when I try to reallocate a 2d int array. Trying to narrow down the problem, I generated a small code only with the reallocations. Question: Valgrind complains a bit without crashing. Are these false positives?

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

#define FREE(x)         {free(x);(x)=NULL;}

/* ======================== subroutine for dynamically reallocating 2d int matrix========================== */
int **realloc_2d_int(int **array, int xlen, int ylen)
{
    int i;

    if( (array = (int **) realloc( array,xlen*sizeof(int *)) ) == NULL) ERROR("without enough memory for redefining 2d int array");
    for(i = 0; i < xlen; i++){
        if ( (array[i] = (int *) realloc( array[i],ylen*sizeof(int))) == NULL) ERROR("without enough memory for redefining 2d int matrix array[i]");
    }

    return array;
    }

/* ======================== subroutine for dynamically allocating 2d int matrix========================== */
int **malloc_2d_int(int xlen, int ylen)
{
    int i;
    int **array=NULL;  

    if( (array = (int **) malloc( xlen*sizeof(int *)) ) == NULL) ERROR("without enough     memory for defining 2d int array");
    for(i = 0; i < xlen; i++){
        if ( (array[i] = (int *) malloc( ylen*sizeof(int))) == NULL)  ERROR("without enough       memory for defining 2d int matrix array[i]");
    }

    return array;
}

int main()
{
   int i,**matrix = NULL;
   size_t size = 100, newsize;

   matrix = malloc_2d_int(size,size);

   for(newsize = 2*size; newsize<=100*size; newsize+=size)   
       matrix = realloc_2d_int(matrix,newsize,newsize);

   for(i=0;i<=100*size;i++) FREE(matrix[i]);
   FREE(matrix);

   return 0;
}

Edit: And the corresponding Valgrind errors are:

==18369== Memcheck, a memory error detector
==18369== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==18369== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==18369== Command: ./test_realloc
==18369== 
==18369== Conditional jump or move depends on uninitialised value(s)
==18369==    at 0x4C2CE3B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18369==    by 0x40079E: realloc_2d_int (test_realloc.c:44)
==18369==    by 0x4008E6: main (test_realloc.c:75)
==18369== 
==18369== Invalid read of size 8
==18369==    at 0x400919: main (test_realloc.c:77)
==18369==  Address 0x1df0c520 is 0 bytes after a block of size 80,000 alloc'd
==18369==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18369==    by 0x400728: realloc_2d_int (test_realloc.c:42)
==18369==    by 0x4008E6: main (test_realloc.c:75)
==18369== 
==18369== Invalid write of size 8
==18369==    at 0x400938: main (test_realloc.c:77)
==18369==  Address 0x1df0c520 is 0 bytes after a block of size 80,000 alloc'd
==18369==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18369==    by 0x400728: realloc_2d_int (test_realloc.c:42)
==18369==    by 0x4008E6: main (test_realloc.c:75)
==18369== 
==18369== 
==18369== HEAP SUMMARY:
==18369==     in use at exit: 0 bytes in 0 blocks
==18369==   total heap usage: 505,100 allocs, 505,100 frees, 13,538,040,000 bytes allocated
==18369== 
==18369== All heap blocks were freed -- no leaks are possible
==18369== 
==18369== For counts of detected and suppressed errors, rerun with: -v
==18369== Use --track-origins=yes to see where uninitialised values come from
==18369== ERROR SUMMARY: 9902 errors from 3 contexts (suppressed: 0 from 0)
1
What errors is valgrind giving? Please include them in the question.MrAlias
This is not a 2D array but only an emulation of it. Probably you can't change the previously existing code, but real 2D arrays are much simpler to handle and you would in particular avoid this notorious problem with 2D emulations.Jens Gustedt
Like? Of course it not implied here it is a physical 2d array in memory if that is what you are talking about. If not, would explain more your reasoning with examples?Rubem_blah

1 Answers

0
votes

In realloc_2d_int, you loop through xlen pointers in the realloced memory, but if the old xlen is not equal the new xlen, you don't have that many pointers to realloc. Let's say the old was 3 and the new was 4. The pointer at index 3 will not be valid for passing to realloc. You need to:

  • If old is greater than new, free the extra old pointers on the end before doing the first realloc so you don't leak memory.
  • If new is greater than old, malloc additional pointers on the end of the array instead of trying to realloc them.

This probably means you're going to need to pass both the old and new xlen into this function.