在 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()
Matrix
和 Matrix_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
这是我的第一个 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()
Matrix
和 Matrix_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