在 C 中取消分配二维数组
Deallocating 2D array in C
无论出于何种原因,我在尝试释放我创建的二维数组时遇到以下错误:
Error in `./a.out': free(): invalid next size (fast): 0x0000000001759310 *** Aborted (core dumped)
我打印出数组的内容,它们是正确的,我可以访问所有元素。但是,我还不能释放它。通过释放循环时会发生错误,即释放双*。非常感谢任何帮助。
谢谢!
代码如下:
/*allocation*/
double **block_mat = (double **) malloc (sizeof(double *) * num_blocks);
int i;
for (i = 0; i <num_blocks; i++){
block_mat[i] = (double *) malloc (sizeof(double) * s);
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
免费(block_mat);
编辑:
发现错误!我分配的内存不足......所以当我打印出我的数组时,它们看起来一切都很好......我分配了大小为 s 的数组,但改为使用 s^2。谢谢大家!
这是不正确的:
free(my_matrix);
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
顺序至少应该是这样的:
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
你确定这些指针都是用不同的 mallocs 分配的吗?
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
free(block_mat);
如果其中两个是同一个指针,那么您正在尝试释放某物两次。
您为每个 block_mat[i]
的 s
双打分配 space。稍后,您访问
block_mat[i][block_index] = 0;
block_index++;
但你永远不会检查 block_index
是否越界,但确实如此。
如果写入超过 s
分配的双精度数,则可能会破坏后续指针的内部控制数据,该指针通常位于 malloc
返回的指针之前,并且需要free
.
完好无损
您有几个问题会影响分配。第一,如果调用 strtol
失败怎么办?
s = (int)strtol(argv [3], &ptr, 10);
您应该检查转换:
#include <errno.h>
...
else {
errno = 0;
long tmp = strtol(argv [3], &ptr, 10);
if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
(errno != 0 && tmp == 0)) {
perror ("strtol");
exit (EXIT_FAILURE);
}
if (ptr == argv[3]) {
fprintf (stderr, "No digits were found\n");
exit (EXIT_FAILURE);
}
s = (int)tmp;
}
接下来,通过分配和释放,您走在了正确的轨道上,但是不要使用 malloc 的 return。投射 return 只会增加难以调试错误的机会。在分配指针到指针到双精度的指针时,您需要根据需要分配尽可能多的指针。 (num_blocks
) 在你的情况下。在计算分配的大小时,您可以简单地取消引用正在分配的变量,这再次减少了出错的机会:
int i;
double **block_mat = malloc (sizeof *block_mat * num_blocks);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = malloc (sizeof **block_mat * s);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
注意: 您必须在开始引用元素之前初始化 block_mat
中的所有值,以防止以后引用未分配的值。 (例如 double result = block_mat[i][j] * Pi;
)考虑添加:
block_mat[i] = malloc (sizeof **block_mat * s);
/* check for failure */
block_mat[i] = 0.0;
注意:分配数值矩阵时,考虑使用calloc
而不是malloc
,因为它会将所有值初始化为'0'
并防止无意中取消引用未赋值的值——这是 未定义的行为。使用 calloc
你会得到:
int i;
double **block_mat = calloc (num_blocks, sizeof *block_mat);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = calloc (s, sizeof **block_mat);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
注意: 当 s
大于 1
时,您将在每个指针处分配 space 多于一个双精度值。注意会阻止您这样做,但您有责任处理每个值的偏移量。 (例如 result = *(block_mat[i] + j + n * sizeof **block_mat) * Pi;
,其中 n 是 0 <= n < s
)如果您在每个指针中存储多个双精度数,请考虑改用 pointer-to-struct
。例如:
typedef struct point {
double x;
double y;
double z;
} point;
无论出于何种原因,我在尝试释放我创建的二维数组时遇到以下错误:
Error in `./a.out': free(): invalid next size (fast): 0x0000000001759310 *** Aborted (core dumped)
我打印出数组的内容,它们是正确的,我可以访问所有元素。但是,我还不能释放它。通过释放循环时会发生错误,即释放双*。非常感谢任何帮助。
谢谢!
代码如下:
/*allocation*/
double **block_mat = (double **) malloc (sizeof(double *) * num_blocks);
int i;
for (i = 0; i <num_blocks; i++){
block_mat[i] = (double *) malloc (sizeof(double) * s);
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
免费(block_mat);
编辑: 发现错误!我分配的内存不足......所以当我打印出我的数组时,它们看起来一切都很好......我分配了大小为 s 的数组,但改为使用 s^2。谢谢大家!
这是不正确的:
free(my_matrix);
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
顺序至少应该是这样的:
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
你确定这些指针都是用不同的 mallocs 分配的吗?
free(my_matrix->vals);
free(my_matrix->cols);
free(my_matrix->rows);
free(my_matrix);
for (i = 0; i < num_blocks; i++){
free(block_mat[i]);
}
free(block_mat);
如果其中两个是同一个指针,那么您正在尝试释放某物两次。
您为每个 block_mat[i]
的 s
双打分配 space。稍后,您访问
block_mat[i][block_index] = 0;
block_index++;
但你永远不会检查 block_index
是否越界,但确实如此。
如果写入超过 s
分配的双精度数,则可能会破坏后续指针的内部控制数据,该指针通常位于 malloc
返回的指针之前,并且需要free
.
您有几个问题会影响分配。第一,如果调用 strtol
失败怎么办?
s = (int)strtol(argv [3], &ptr, 10);
您应该检查转换:
#include <errno.h>
...
else {
errno = 0;
long tmp = strtol(argv [3], &ptr, 10);
if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
(errno != 0 && tmp == 0)) {
perror ("strtol");
exit (EXIT_FAILURE);
}
if (ptr == argv[3]) {
fprintf (stderr, "No digits were found\n");
exit (EXIT_FAILURE);
}
s = (int)tmp;
}
接下来,通过分配和释放,您走在了正确的轨道上,但是不要使用 malloc 的 return。投射 return 只会增加难以调试错误的机会。在分配指针到指针到双精度的指针时,您需要根据需要分配尽可能多的指针。 (num_blocks
) 在你的情况下。在计算分配的大小时,您可以简单地取消引用正在分配的变量,这再次减少了出错的机会:
int i;
double **block_mat = malloc (sizeof *block_mat * num_blocks);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = malloc (sizeof **block_mat * s);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
注意: 您必须在开始引用元素之前初始化 block_mat
中的所有值,以防止以后引用未分配的值。 (例如 double result = block_mat[i][j] * Pi;
)考虑添加:
block_mat[i] = malloc (sizeof **block_mat * s);
/* check for failure */
block_mat[i] = 0.0;
注意:分配数值矩阵时,考虑使用calloc
而不是malloc
,因为它会将所有值初始化为'0'
并防止无意中取消引用未赋值的值——这是 未定义的行为。使用 calloc
你会得到:
int i;
double **block_mat = calloc (num_blocks, sizeof *block_mat);
/* check allocation for failure */
for (i = 0; i <num_blocks; i++){
block_mat[i] = calloc (s, sizeof **block_mat);
/* check allocation for failure */
}
/*freeing*/
for (i = 0; i < num_blocks; i++){
free (block_mat[i]);
}
free(block_mat);
注意: 当 s
大于 1
时,您将在每个指针处分配 space 多于一个双精度值。注意会阻止您这样做,但您有责任处理每个值的偏移量。 (例如 result = *(block_mat[i] + j + n * sizeof **block_mat) * Pi;
,其中 n 是 0 <= n < s
)如果您在每个指针中存储多个双精度数,请考虑改用 pointer-to-struct
。例如:
typedef struct point {
double x;
double y;
double z;
} point;