我正在使用realloc获得意外行为

时间:2019-12-11 09:58:08

标签: c visual-studio-2019 realloc

由于某种原因,我每运行2-3次程序就会得到意外值,例如-842150451 -842150451,而每隔2次我得到正确的结果: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++;
    }
}

2 个答案:

答案 0 :(得分:0)

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


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

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

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

此外,您永远不会在此数组中写入任何值。为*ptrArr分配一个值最多将覆盖该数组的第一个值。


另一个问题是您最初将arr复制到ptrArr。稍后,如果flag == 1您重新分配arr。重新分配意味着可以释放输入数组(空闲),并分配一个更大的新块。在这种情况下,当您以后为*ptrArr分配一个值时,您将不会写在arr中。您将在不应该写的释放空间中进行写操作。更糟糕的是,如果在此期间重新分配了该空间,则可能会错误地覆盖有效数据,这是一个非常讨厌的调试问题。

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

这意味着当mat[row][indexCol]时,您必须附加 arr到数组flag == 1


这是处理数组的方法。

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

请注意,分配一个0字节的块取决于实现。它可能会或可能不会返回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 == NULL时是否cnt == 0并不重要,因为arr时从未访问过cnt == 0


代码中还存在一个错误,该错误连续定位最大值。

您将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

答案 1 :(得分:0)

您的问题很可能是由于使用//Doing it in a Using statement to properly dispose of the StreamReader using (StreamReader sr = new StreamReader(path)) { while (sr.Peek() > -1) { Console.WriteLine(sr.ReadLine()); } } 而引起的。您可以将其初始化到ptrAtr的开头,但随后要初始化arr realloc,因此无法保证arr将保留在相同的存储位置,这意味着{{ 1}}将不再指向它。

像这样在arr中使用索引会更好。

ptrArr