[英]Passing numpy arrays in Cython to a C function that requires dynamically allocated arrays
[英]Passing two different dynamically allocated arrays to function in C
我试图将分配在堆上的两个数组(一个NxN,一个1XN)传递给一个函数。 我一直得到分段错误11。根据gdb
,seg错误发生在double c=matrix[i][j]/matrix[j][j]
。 我忍不住觉得问题出在我在函数中声明参数的方式。
double **Mat_A=(double **) malloc(dim_matrix*sizeof(double));
double *Vec_B=(double *) malloc(dim_vector*sizeof(double));
//read in numbers from file
for(int i=0; i<dim_matrix; i++)
{
for(int j=0; j<dim_matrix; j++)
{
fscanf(f1, "%lf%*[^\n]%*c", &Mat_A[i][j]);
}
}
for(int k=0; k<dim_vector; k++)
{
fscanf(f2, "%lf%*[^\n]%*c", &Vec_B[k]);
}
void reduce_mat(double **matrix, double *vector, int row, int column)
{
int i;
int j;
for( j = 0; j < row; j++ )
{
for( i = 0; i < column; i++ )
{
if ( i != j )
{
double c= matrix[i][j] / matrix[j][j];
for( int k = 0; k < column + 1; k++ )
{
matrix[i][k] = matrix[i][k] - c * matrix[j][k];
}
}
}
}
printf("\nSolution:\n");
for(i=0; i<column; i++)
{
vector[i]=matrix[i][column+1]/matrix[i][i];
printf("\nx%d=%f\n",i,vector[i]);
}
return;
我假设column
是矩阵中列的序数,所以如果值是5
则这些列的索引为0..4
。
但是,在您的if( i != j )...
语句中,您有以下内容:
k < column + 1 // so `k == column` can be true
...
matrix[i][k]
这意味着您要使用偏移量i * row + k
取消引用matrix
指针,该偏移量可能超出范围。
这假定矩阵的缓冲区在每一行的末尾(对于其他列)没有多余的空间,在缓冲区的末尾也没有额外的行。
由于您没有提供矩阵形状的任何指示,因此我尝试使用非正方形矩阵。 事情似乎并没有像正方形矩阵那样好用,因此显示的代码可以在6x6正方形矩阵和6号矢量下工作。
这是使用GCC 7.2.0在运行macOS 10.13.1 High Sierra的Mac上对我来说可以正常运行的代码。 它从标准输入读取所有数据; 它写入标准输出。
dump_matrix()
和dump_vector()
函数代表有用的函数类,该类以可读格式转储数据结构。 更通用的版本将文件流作为第一个参数,并在最后添加fflush(fp)
,并可能检查非空指针。 有时,它也有助于打印地址。
#include <stdio.h>
#include <stdlib.h>
static void reduce_mat(int row, int col, double matrix[row][col], double vector[col]);
static void dump_matrix(const char *tag, int row, int col, double matrix[row][col]);
static void dump_vector(const char *tag, int col, double vector[col]);
int main(void)
{
FILE *f1 = stdin;
int row = 6;
//int col = 8;
int col = 6;
double (*Mat_A)[col] = malloc(row * col * sizeof(double));
double *Vec_B = malloc(col * sizeof(double));
// read in numbers from standard input
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (fscanf(f1, "%lf", &Mat_A[i][j]) != 1)
{
fprintf(stderr, "Read error matrix[%d,%d]\n", i, j);
exit(1);
}
}
}
for (int k = 0; k < col; k++)
{
if (fscanf(f1, "%lf", &Vec_B[k]) != 1) // Beware - changed to f1
{
fprintf(stderr, "Read error vector[%d]\n", k);
exit(1);
}
}
dump_matrix("Matrix A", row, col, Mat_A);
dump_vector("Vector B", col, Vec_B);
reduce_mat(row, col, Mat_A, Vec_B);
dump_vector("Solution Vector", col, Vec_B);
dump_matrix("Reduced Matrix", row, col, Mat_A);
free(Mat_A);
free(Vec_B);
return 0;
}
static void reduce_mat(int row, int col, double matrix[row][col], double vector[col])
{
for (int j = 0; j < row; j++)
{
for (int i = 0; i < col; i++)
{
if (i != j)
{
double c = matrix[i][j] / matrix[j][j];
for (int k = 0; k < col + 1; k++)
{
matrix[i][k] = matrix[i][k] - c * matrix[j][k];
}
}
}
}
printf("\nSolution:\n");
for (int i = 0; i < col; i++)
{
vector[i] = matrix[i][col + 1] / matrix[i][i];
printf("x%d = %9.2f\n", i, vector[i]);
}
putchar('\n');
}
static void dump_matrix(const char *tag, int row, int col, double matrix[row][col])
{
printf("%s (matrix[%d][%d]):\n", tag, row, col);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
printf("%9.2f", matrix[i][j]);
putchar('\n');
}
}
static void dump_vector(const char *tag, int col, double vector[col])
{
printf("%s (vector[%d]):\n", tag, col);
for (int i = 0; i < col; i++)
printf("%9.2f", vector[i]);
putchar('\n');
}
给定一个包含42个介于0和1000之间的随机浮点数的输入文件,将产生:
Matrix A (matrix[6][6]):
994.60 955.00 769.60 32.10 950.10 555.90
105.50 857.50 606.10 289.30 592.60 95.60
437.50 90.20 264.10 262.40 879.00 708.20
236.40 1.00 273.90 405.60 4.80 199.90
114.90 713.70 433.90 739.00 42.10 184.80
895.40 911.00 161.80 829.20 487.90 864.80
Vector B (vector[6]):
543.10 258.70 556.60 101.50 685.30 899.30
Solution:
x0 = 0.76
x1 = 0.00
x2 = 0.00
x3 = -0.00
x4 = -0.00
x5 = -0.00
Solution Vector (vector[6]):
0.76 0.00 0.00 -0.00 -0.00 -0.00
Reduced Matrix (matrix[6][6]):
994.60 0.00 0.00 0.00 0.00 0.00
0.00 756.20 0.00 0.00 0.00 0.00
-0.00 0.00 154.36 0.00 0.00 0.00
-0.00 0.00 0.00 -115.16 0.00 0.00
-0.00 0.00 0.00 0.00 -7025.36 0.00
-0.00 0.00 0.00 0.00 0.00 -237.16
我不知道这是否是一个适当的计算,但是与问题AFAICT中的代码相同(任何此类更改都是偶然的和无意的),我不知道。 修改了功能矩阵参数的类型,使其更易于管理,并且将内存分配分配给了指向double
值数组的适当指针。 请注意,对于6x6阵列,实际上没有必要使用动态内存分配。 在堆栈上进行普通分配会很好。
可变长度数组(VLA)有用吗? 它们确实简化了很多矩阵处理代码。
对于VLA的堆栈分配,您确实需要注意堆栈有足够的空间。 如果没有,您的程序可能会崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.