在 for 循环和 C 中的 if 语句中使用 Malloc 数组 - 导致分段

Using Malloc Arrays inside a for loop and an if statement in C - Leading to Segmentation

这是我的第一个 post,很抱歉,如果它不符合我应该 post 的标准,如果我放置代码的方式有任何问题,请说我会在以后的 post 中考虑到这一点。我试着尽可能多地注释代码,也许有点太多了。

所以代码的想法是采用普通矩阵,然后将其以简化形式存储,这很好用,但是当我还希望将其与向量相乘时,它失败了。

代码失败,因为当我使用 if 语句执行双 for 循环时它会分段,我不知道为什么。

如果我单独指定元素,它工作正常,但是当我尝试在 if 语句中为 Matrix_R 增加应该 select 的元素时失败。

如有任何帮助,我们将不胜感激。谢谢!!

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    int i;
    int j;
    int n;
    int m;
    int k=0;
    double * Vin;
    double * Vout_M;
    double * Vout_MR;
    double ** Matrix;
    double ** Matrix_R;

    //Vout_M and Vout_MR are output vectors for the two possible inputted matricies
    //Matrix_R is the reduced form of Matrix

    n=4;

    Vin = malloc(n*sizeof(double));
    Vout_M = malloc(n*sizeof(double));
    Vout_MR = malloc(n*sizeof(double));
    Matrix = malloc(n*sizeof(double*));

    for(i=0;i<n;i++)
        Matrix[i] = malloc(n*sizeof(double));

    //Allocates memory for the arrays

    for(i=0;i<n;i++){
    Vin[i]=1;
    Vout_M[i]=0;
    Vout_MR[i]=0;
    }

    //Initiates the vector arrays

    for(i=0;i<n;i++)
    for(j=0;j<n;j++)
    Matrix[i][j]=0;

    //Initiates the Matrix

    Matrix[2][3]=5;
    Matrix[0][2]=10;

    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            if(Matrix[i][j]!=0)
                m++;

    //Scans through to determine what size the reduced array should be
    //In Future, this could be set up to read from a text file, and so RAM isn't used to store the array to find elements

    Matrix_R = malloc(m*sizeof(double*));
    for(i=0;i<m;i++)
        Matrix_R[i] = malloc(3*sizeof(double));

    for(i=0;i<m;i++)
        for(j=0;j<3;j++)
        Matrix_R[i][j]=0;

    //Produces the reduced array, and initiates it

    printf("\n");

    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            if(Matrix[i][j]!=0){
            Matrix_R[k][0]=Matrix[i][j];
            Matrix_R[k][1]=i;
            Matrix_R[k][2]=j;
            k++;
            }

    //Scans through the Matrix array and outputs to the Matrix_R array

    for(i=0;i<k;i++)
    printf("Matrix_R[%d][0] = %lf, Matrix_R[%d][1] = %lf, Matrix_R[%d][2] = %lf\n",i,Matrix_R[i][0],i,Matrix_R[i][1],i,Matrix_R[i][2]);

    //Checks if it is storred correctly -- this outputs fine

    //Now first do the multiplication between the normal matrix and vector --- Matrix * Vector

    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            Vout_M[i] += Matrix[i][j]*Vin[j];

    for(i=0;i<n;i++)
    printf("\nVout_M[%d] = %lf",i,Vout_M[i]);
    printf("\n");

    //Prints the output from a standard Matrix * Vin in the form of Vout_M

    k=0;
    for(i=0;i<n;i++)
        for(j=0;j<n;j++){
            if(i  == Matrix_R[k][1] && j == Matrix_R[k][2]){
                Vout_MR[i] += Matrix_R[k][0]*Vin[j];
                k++;
            }}

    //Goes through standard matrix-vector multiplication, using reduced matrix
    //SEGMENTS :: When trying to go through an if statement and incrementing k.
    //i.e. If I set k=int, and then not increase it in the if statement it works.


    for(i=0;i<n;i++)
    printf("\nVout_MR[%d] = %lf",i,Vout_MR[i]);
    printf("\n");

    //Outputs the Vout_MR which is from Matrix_R * VIN

    free(Vin);
    free(Vout_M);
    free(Vout_MR);

    for(i=0;i<n;i++)
        free(Matrix[i]);

    for(i=0;i<m;i++)
        free(Matrix_R[i]);


return 0;
}

在您的代码中,您从未初始化

 int m;

并且您正在使用

中未初始化的值
if(Matrix[i][j]!=0)
                m++;

Matrix_R = malloc(m*sizeof(double*));

它会产生一个先读后写的场景。行为未定义。

此外,始终检查 malloc() 的 return 值以确保成功。

您可以[并且应该]使用%f 格式说明符来打印双精度值。变化

 printf("\nVout_M[%d] = %lf",i,Vout_M[i]);

 printf("\nVout_M[%d] = %f",i,Vout_M[i]);

接下来,您 free()d 了所有 Matrix[i]Matrix_R[i],但您自己忘记了 free() MatrixMatrix_R .


编辑

在您的代码中,

中的值 k 没有边界检查
if(i  == Matrix_R[k][1] && j == Matrix_R[k][2])

一旦你的 k >= m,你将访问越界内存调用未定义的行为。副作用是分段错误。

很可能,在您的情况下,m 的值是 2,当 k 通过 k++ 变为 2 时,下一次访问i == Matrix_R[k][1] 生成越界内存访问。

for(i=0;i<n;i++)
    for(j=0;j<n;j++){
        if(i  == Matrix_R[k][1] && j == Matrix_R[k][2]){
            Vout_MR[i] += Matrix_R[k][0]*Vin[j];
            k++;
        }}

在这里你不断递增 k 并且不能保证 k<m 所以当你不断递增 k 有一个访问 Matrix_R[k][1] 其中 k>m 通向 UB