我使用 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 == NULL
当 cnt == 0
时没有关系,因为 cnt == 0
时永远不会访问 arr
。
代码中还有一个错误,就是定位一行中的最大值。
您将 tempCol
初始化为 0,并将值与其进行比较。如果该行仅包含小于 0 的负值,您的算法将无法找到该行中的最大值。
为了找到连续的最大值,您有两种选择。
用尽可能小的值初始化 tempCol:INT_MIN (#include )。
使用下面的代码消除了 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];
}
}
出于某种原因,我 运行 程序每运行 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
.
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 == NULL
当 cnt == 0
时没有关系,因为 cnt == 0
时永远不会访问 arr
。
代码中还有一个错误,就是定位一行中的最大值。
您将 tempCol
初始化为 0,并将值与其进行比较。如果该行仅包含小于 0 的负值,您的算法将无法找到该行中的最大值。
为了找到连续的最大值,您有两种选择。
用尽可能小的值初始化 tempCol:INT_MIN (#include
)。 使用下面的代码消除了
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];
}
}