cmemory-managementsegmentation-faultreallocmemory-reallocation

Segmentation Fault accessing array positions after realloc


Let's suppose I have this function:

void arrayExtendDouble(int **ptArr, int *size)
{    
    *ptArr = realloc(*ptArr, (*size * 2) * sizeof(int));


    for(int i = (*size * 2) - 1; i >= *size; i--)
        ptArr[i] = fib(i); //this will throw SEG FAULT

    *size *= 2;       
}

Note: I am a student and this is the valid resolution a teacher gave.

Now, the only way i can make this work is like this:

    void fibArrayExpand(int **ptArr, int *size)
    {    
        int *ptArrNew = realloc(*ptArr, (*size * 2) * sizeof(int));


        for(int i = (*size * 2) - 1; i >= *size; i--)
            ptArrNew[i] = fib(i);

        *size *= 2;       

        *ptArr = ptArrN;
    }

Supposedly the first one (teacher's) is correct and the second one (mine) it's not because i do extra steps not needed.

I would like to know why does it throw segmentation fault, is it supposed to do so or is the function well written?


Solution

  • The first snippet isn't correct. ptAtr isn't the pointer to the ints; it's a pointer to another pointer, *ptAtr, which is the pointer to the ints. As such,

    ptArr[i] = fib(i);
    

    should be

    (*ptArr)[i] = fib(i);
    

    Alternate explanation

    It's pretty easy to see the following code achieves the correct result:

    void arrayExtendDouble(int** arr_ptr, int* size_ptr)
    {    
        // Copy values from caller.
        int* arr = *arr_ptr;
        int size = *size_ptr;
    
        arr = realloc(arr, (size * 2) * sizeof(int));
    
        for(int i = (size * 2) - 1; i >= size; i--)
            arr[i] = fib(i);
    
        size *= 2;
    
        // Pass back modified values to caller.
        *arr_ptr  = arr;
        *size_ptr = size;
    }
    

    You might notice that arr and *arr_ptr have the same value, and so do size and size_ptr. That means we could simply replace all instances of arr and size with *arr_ptr and *size_ptr respectively.

    void arrayExtendDouble(int** arr_ptr, int* size_ptr)
    {    
        *arr_ptr = realloc(*arr_ptr, (*size_ptr * 2) * sizeof(int));
    
        for(int i = (*size_ptr * 2) - 1; i >= *size_ptr; i--)
            (*arr_ptr)[i] = fib(i);
    
        *size_ptr *= 2;
    }
    

    Note that (*arr_ptr)[i] = fib(i); is used instead of arr[i] = fib(i);. The first snippet you posted is therefore incorrect.