Search code examples
cheap

realloc error in C when resizing the heap


I want to use realloc in C in an insert function for heap. This is the code:

typedef struct MaxHeap {
    int size;
    int* heap;
} MaxHeap;

void max_insert(MaxHeap* max_heap, int* key_index, int key) { // O(logn)
    max_heap->heap = realloc((max_heap->size+1), sizeof * max_heap->heap);
    max_heap[max_heap->size] = N_INF;
    max_heap->size += 1;
    increase_key(max_heap, key_index, max_heap->size, key)
}

And I get this warning:

warning: passing argument 1 of ‘realloc’ makes pointer from integer without a cast [-Wint-conversion] and I tried this fix:

max_heap->heap = realloc((max_heap->heap), (max_heap->size+1) * sizeof(*(max_heap->heap)));

Update

I did this:

void max_insert(MaxHeap* max_heap, int* key_index, int key) { // O(logn)
    int* temp = realloc (max_heap->heap, (max_heap->size + 1) * sizeof (*(max_heap->heap)));
    if (!temp) exit(1);
    max_heap->heap = temp;
    max_heap->heap[max_heap->size] = N_INF;
    max_heap->size += 1;
    increase_key(max_heap, key_index, max_heap->size, key);
    temp = 0;
}

And I got this error realloc(): invalid old size


Solution

  • You've swapped the arguments to realloc().

    (max_heap->size+1)
    

    evaluates to an int, but the first argument to realloc() expects a void * pointer. Replace it with:

    (max_heap->heap);
    

    And the call to realloc() becomes:

    realloc (max_heap->heap, (max_heap->size + 1) * sizeof (*(max_heap->heap)));
    

    Note that this fails for two reasons:

    1. There was not enough memory and realloc() returned NULL, which will go unnoticed because we didn't check the return value of realloc(). A subsequent operation would now be writing to / dereferencing / reading from NULL, which would invoke undefined behaviour.
    2. If realloc() returned NULL, we would lose access to the original memory, which would result in a memory leak.

    Fix:

    Use a temporary pointer to hold the return value of realloc():

    int *tmp = realloc (... , ...);
    
    if (!tmp) {
        perror ("realloc()");
        /* realloc() was unable to allocate memory.
         * The original memory is left untouched.
         * Handle error here.
         */
    } 
    /* Now we can assign the result to `max_heap->heap`: */
    max_heap->heap = tmp;
    tmp = 0;      /* This is unnecessary, but eliminates a dangling pointer. */