动态释放 2D 矩阵崩溃

Dynamic deallocation of a 2D matrix crashing

提问人:Yacine Megrah 提问时间:1/11/2022 最后编辑:LundinYacine Megrah 更新时间:1/11/2022 访问量:76

问:

我有一个函数,在开始时分配 2D 矩阵,还有一个在最后使用它的函数。

int** CreatMat(int N){
    int i,**T;
    T = (int**)malloc(sizeof(int*)*N);
    if(T!=NULL){
        for(i=0;i<N;i++){
            T[i]=(int*)malloc(sizeof(int)*N);
            if(T[i]==NULL){
                printf("\nCreatMat()::Allocation failed at block %d",i);
                for(i=i;i>=0;i--){
                    free(T[i]);
                    T[i]=NULL;
                }
                free(T);
                T=NULL;
                return T;
            }
        }
    }
    return T;
}

//Free a dynamic matrix.
void FreeMat(int** T,int N){
    int i;
    for(i=0;i<N;i++){
        free(T[i]);
        T[i]=NULL;
    }
    free(T);
    T = NULL;
}

不知何故,正在崩溃。有什么帮助吗?FreeMat()

完整代码在这里

~卡顿在这里修复代码

c 函数 矩阵 malloc

评论

0赞 Weather Vane 1/11/2022
在分配和释放之间
0赞 Yacine Megrah 1/11/2022
编辑这些矩阵中的整数并打印它们的其他函数,我想在这里保持简短,如果你愿意,我可以添加它们。
1赞 dbush 1/11/2022
这段代码很好。问题出在你没有向我们展示的代码中。想必你踩到了不应该踩到的内存,所以通过 valgrind 运行你的代码来找到问题。
1赞 Weather Vane 1/11/2022
欢迎!请以文本形式发布最小可重现示例,这是显示故障的最短完整代码(带有运行时输入)。最好的方法是复制/粘贴,在您检查后,它确实表现出所描述的行为。
1赞 wildplasser 1/11/2022
啊哈,三星程序员!普隆克

答:

0赞 Weather Vane 1/11/2022 #1

在功能上,这个main()

int **T, **S;
if(Grids_Init(T, S) != 0)

不会影响局部变量的值,并且这些变量仍未初始化,然后继续释放这些不确定的指针。ST

您可以使用函数初始化其中一个,返回指针并将其分配给 .然后同样。TS

这比使用三星指针更可取:请参阅 C 中的三指针:这是风格问题吗?一个答案以

使用三重指针会损害可读性和可维护性。

0赞 0___________ 1/11/2022 #2

您不会创建 2D 数组,而只能创建指针数组。让您的生活更轻松,并找到真正的 2D 阵列。此外,请使用正确的尺寸类型size_t

void CreatMat(size_t N, int (**array)[N])
{
    *array = malloc(N * sizeof(**array));
}

int main(void)
{
    int (*array)[N];
    CreatMat(1000, &array);

    /* some code */

    free(array);
}

看看它有多容易。

评论

0赞 Yacine Megrah 1/11/2022
谢谢,这将使事情变得更容易,但是如果我们要定义一个类型,我们将如何定义它?我认为,使用和传递 an 将始终返回 8 位。arraysizeof()*******ptr
0赞 0___________ 1/11/2022
@YacineMegrah我不明白.你的评论没有多大意义*******ptr
0赞 Yacine Megrah 1/11/2022
我的意思是将任何指针传递给将始终返回 8;sizeof()
0赞 0___________ 1/11/2022
@YacineMegrah你不明白我的代码是做什么的。首先测试它,不要假设任何事情
0赞 Yacine Megrah 1/11/2022
如何访问 IN ?是吗?T[i][j]main()array[i][j]
0赞 Yacine Megrah 1/11/2022 #3

响应 @0_______

#include <stdlib.h>

int main(){
    int i,j;
    int (*T)[7];
    //(*T)[7] = malloc(7*sizeof(&(*T))); is wrong
    T = malloc(7*sizeof(*T));
    for(i=0;i<7;i++){
        printf("\n");
        for(j=0;j<7;j++){
            printf("%d  ");
        }
    }
    free(T);

    return 0;
}

评论

0赞 Lundin 1/11/2022
您可能会发现不那么令人困惑且更易于阅读。T = malloc( sizeof(int[7][7]) );
0赞 Yacine Megrah 1/11/2022
@Lundin如果可以的话,我很想写下,“它有资格吗?”是我关心的问题。(*T)[7] = malloc(7*sizeof(&(*T)));
0赞 0___________ 1/11/2022
不,这是错误的!!如果你想要 7x7T = malloc(7*sizeof(*T));
0赞 0___________ 1/11/2022
@Lundin它容易出错。如果更改 的定义,则需要更改所有 sizeofs。这个想法是使用对象而不是 sizeof 中的类型来使您的代码不容易出错T
0赞 Lundin 1/11/2022
&*与不使用任何一个运算符相同,因此您最终会得到而不是预期的。sizeof(T)sizeof(*T)
0赞 wildplasser 1/11/2022 #4
  • 将矩阵表示为指针数组是次优的:它浪费了内存和时间,并且引用的位置会更糟
  • 一旦你认为你需要的不仅仅是一个双指针,你就应该重新考虑你的数据:使用一些结构来表示矩阵。

一个简单的例子:


#include <stdlib.h>

struct matrix {
        unsigned nrow;
        unsigned ncol;
        // int flags;
        double *data;
        };

/*****************************************************************/
static size_t nrc2idx(unsigned ncol, unsigned irow, unsigned icol)
{
return (irow*ncol) + icol;
}

struct matrix *matrix_new(unsigned nrow, unsigned ncol)
{
struct matrix *mp;

mp = malloc (sizeof *mp);
if (!mp) return mp;
mp->data = malloc (sizeof *mp->data * nrow * ncol);
if ( !mp->data) {
        free (mp);
        return NULL;
        }
mp->nrow = nrow;
mp->ncol = ncol;

return mp;
}

现在,使用这种结构将两个矩阵相乘有多难? 示例代码:


struct matrix *matrix_mult(struct matrix *left, struct matrix *right)
{
struct matrix *result;
unsigned ii,jj;

if (!left || !right) return NULL;
if (left->ncol != right->nrow) return NULL;

result = matrix_new(left->nrow, right->ncol);
if (!result) return NULL;

for (ii=0; ii < result->nrow; ii++) {
        for (jj=0; jj < result->ncol; jj++) {
                size_t uu;
                unsigned kk;
                double sum ;
                sum = 0.0;
                for (kk=0; kk < left->ncol; kk++) {
                        size_t aa, bb;
                        aa = nrc2idx(left->ncol, ii, kk);
                        bb = nrc2idx(right->ncol, kk, jj);
                        sum += left->data[aa] * right->data[bb];
                        }
                uu = nrc2idx(result->ncol, ii, jj);
                result->data[uu] = sum;
                }
        }
return result;
}

评论

0赞 0___________ 1/11/2022
它也是次优的。对未无符号的大小 () 使用正确的类型。返回过多容易出错(而不是使用正检查而不是负检查)size_t
0赞 Lundin 1/11/2022
如果沿着这条路线走下去,则应改用灵活的数组成员。否则,您还没有真正解决程序的碎片化 malloc 调用和毫无意义的间接级别。
0赞 wildplasser 1/11/2022
我说这是一个简化的例子。它只是为了展示“封装”的概念(顺便说一句:恕我直言,灵活的数组成员对 OP 来说太难了,因为他仍在为指针和数组而苦苦挣扎)
0赞 Yacine Megrah 1/11/2022
我明白你的意思,但是,我试图为我的项目保留格式,并且在我实现它时也缺乏维护此代码完整性的技能,因为此 OP 只是一个用于SDL2_project的库。T[i][j]