我使用 realloc 时出现意外行为

i'm getting unexpected behavior using realloc

出于某种原因,我 运行 程序每运行 2-3 次就会得到意想不到的值,例如 -842150451 -842150451,每隔一次我就会得到正确的结果:7 9.

我是一名学生,如果代码有点学术化,请见谅。

请看代码:

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);

}

我怀疑问题出在 realloc 块上:

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++;
    }
}

您最初为一个整数分配了空间的数组,但您从未设置该整数值。我猜这是因为分配一个 0 字节的块 returned NULL 你认为是一个错误。


另一个令人困惑的代码片段是

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

为什么要将 cnt 初始化为 1 如果您希望分配的数组的大小是我们 flag == 1 的次数?

此外,您永远不会在此数组中写入任何值。给 *ptrArr 赋值最多只能覆盖数组的第一个值。


另一个问题是您最初将 arr 复制到 ptrArr。稍后,如果 flag == 1 你重新分配 arr。重新分配意味着可以释放(释放)输入数组并分配一个新的更大的块。在这种情况下,当您稍后为 *ptrArr 赋值时,您将不会写入 arr。你会在你不应该写的地方写 deallocated space 。更糟糕的是,如果 space 同时被重新分配,您可能会错误地覆盖有效数据,这是一个非常难以调试的问题。

我的印象是您认为重新分配会在块前面创建 space。那是不正确的。 ralloc,扩展块。因此,当块的大小增加时,会在块的末尾添加空间。

这意味着当 flag == 1.

时,您必须 append mat[row][indexCol] 到数组 arr

下面是您应该如何处理数组。

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

请注意,分配 0 字节的块取决于实现。它可能会也可能不会 return NULL。在这里,我们决定一个空数组为 NULL,并且有 cnt == 0

以下代码将值 mat[row][indexCol] 附加到数组:

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

这在 arr 为 NULL 时有效,因为 realloc 将分配一个新块。

要打印数组中的所有值:

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

如果 arr == NULLcnt == 0 时没有关系,因为 cnt == 0 时永远不会访问 arr


代码中还有一个错误,就是定位一行中的最大值。

您将 tempCol 初始化为 0,并将值与其进行比较。如果该行仅包含小于 0 的负值,您的算法将无法找到该行中的最大值。

为了找到连续的最大值,您有两种选择。

  1. 用尽可能小的值初始化 tempCol:INT_MIN (#include )。

  2. 使用下面的代码消除了 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

您的问题很可能是由于使用 ptrAtr。您将其初始化为 arr 的开头,但稍后您 realloc arr 并且无法保证 arr 将保留在相同的内存位置,这意味着 ptrArr 将不再指向它。

像这样使用 arr 的索引会更好..

int cnt = 0;
arr = (int*)malloc(cnt * sizeof(int));

// stuff happens

if (flag == 1)
    {
        arr = realloc(arr, (cnt + 1) * sizeof(int));
        printf("mat[%d][%d] = %d\n", row, indexCol, mat[row][indexCol]);
        arr[cnt++] = mat[row][indexCol];
    }
}