Search code examples
cvisual-studio-2019realloc

i'm getting unexpected behavior using realloc


for some reason, every 2-3 times that i run the program i get unexpected values, such as -842150451 -842150451, and every other time i get the correct result: 7 9.

i'm a student, so sorry if the code is a little academic.

please see code:

int mat[ROW][COL] = {
    {2,-3,5,1,2},
    {2,4,7,7,1},
    {1,9,7,3,0}
};

int row, col, tempRow = 0, tempCol = 0, indexCol, indexRow = 0, loopTempRow, flag = 0, cnt = 1, loopTempCol = 0;
int* arr;
int* ptrArr;

arr = (int*)malloc(cnt * sizeof(int)); // mallocating an array with size 1 * int
ptrArr = arr;

if (arr == NULL)    // checking allocation done succefully
{
    printf("Error Allocating Memory\n");
    exit(1);
}


for (row = 0; row < ROW; row++) // starting from row 0 we will wheck col 0,1,2,3,4 for the highest val.
{
    flag = 1;
    tempCol = 0;

    for (col = 0; col < COL; col++)
    {
        if (mat[row][col] > tempCol)
        {
            tempCol = mat[row][col];
            indexCol = col;
        }
    }
    for (loopTempRow = 0; loopTempRow < ROW; loopTempRow++) // then we will check the row of the col index
    {

        if (mat[loopTempRow][indexCol] > tempCol)
        {
            flag = 0;
            break;
        }
    }

    if (flag == 1)
    {
        cnt++;                                                      // this is a counter for realloctaing.
        arr = realloc(arr, (cnt - 1) * sizeof(int));                            // every iteration the arr is increasing by 1
        printf("mat[%d][%d] = %d\n", row, indexCol, mat[row][indexCol]);
        *ptrArr = mat[row][indexCol];                                       // inserting the element into the arr
        ptrArr++;
    }
}

if (cnt == 1)                                           // if the cnt = 1, it means that flag didn't became 1. which meant no value inserted to the arr
    arr = NULL;




for (ptrArr = arr; ptrArr - arr < cnt - 1; ptrArr++)                        // print arr
    printf("%d\t", *ptrArr);

free(arr);

}

i suspect that the problem is with the realloc block:

if (flag == 1)
    {
        cnt++;                                                      // this is a counter for realloctaing.
        arr = realloc(arr, (cnt - 1) * sizeof(int));                            // every iteration the arr is increasing by 1
        printf("mat[%d][%d] = %d\n", row, indexCol, mat[row][indexCol]);
        *ptrArr = mat[row][indexCol];                                       // inserting the element into the arr
        ptrArr++;
    }
}

Solution

  • You initially allocate an array with room for one integer, but you never set that integer value. I guess it is because allocating a block of 0 bytes returned NULL which you assume is an error.


    Another confusing code fragment is

    cnt++;                                       // this is a counter for realloctaing.
    arr = realloc(arr, (cnt - 1) * sizeof(int)); // every iteration the arr is increasing by 1
    

    Why initializing cnt to 1 if you want that the size of the allocated array is the number of times we had flag == 1 ?

    Beside, you never write any value in this array. Assigning a value to *ptrArr would at best overwrite the first value of the array.


    Another problem it that you initially copy arr to ptrArr. Later, if flag == 1 you reallocate arr. A reallocation implies that the input array may be deallocated (free) and a new bigger block is allocated. In this case, when you later assign a value to *ptrArr you won’t write in arr. You will write in deallocated space where you should not write. Worse, if that space is reallocated in the mean time, you may override valid data by mistake, which is a very nasty problem to debug.

    I have the impression that you assume that reallocation creates space in front of the block. That is not correct. ralloc, extends the block. So room is added at the end of the block when its size grows.

    This implies that you have to append mat[row][indexCol] to the array arr when flag == 1.


    Here is how you should handle your array.

    // initialize the array as empty
    int cnt = 0;
    int *arr = NULL;
    

    Note that allocating a block of 0 bytes is implementation dependent. It may or may not return NULL. Here we decide that an empty array is NULL and has cnt == 0.

    The following code appends the value mat[row][indexCol] to the array:

    // append mat[row][indexCol] to the array arr
    arr = realloc(arr, (cnt+1)*sizeof(int));
    arr[cnt++] = mat[row][indexCol];
    

    This works when arr is NULL because realloc will allocate a new block.

    To print all values in the array:

    for(int i = 0; i < cnt; i++)
        printf("%d\t", arr[i]);
    

    It doesn’t matter if arr == NULL when cnt == 0 because arr is never accessed when cnt == 0.


    There is also a mistake in the code that locates the biggest value in a row.

    You initialize tempCol with 0, and compare values with it. If the row contains only negative values that are all smaller than 0, your algorithm will fail to find the biggest value in the row.

    In order to find the biggest value in a row, you have two options.

    1. Initialize tempCol with the smallest possible value : INT_MIN (#include <limits.h>).

    2. Use the following code that removes the need of tempCol.

    indexCol = 0;
    for (col = 1; col < COL; col++)
        if (mat[row][col] > mat[row][indexCol])
            indexCol = col;
    // here, indexCol is the index of biggest value in the row