我正在写一个c代码的问题。它必须乘以给定维度的2个矩阵(用0-9之间的random整数填充)(mxn乘以nxm,结果是mxm矩阵)。矩阵由列填充。此外,我必须输出整个程序的计算时间和执行计算的函数的执行。
我在执行应用程序时遇到“glibc detected”错误。我知道这是由于我的程序中的堆损坏,很可能是由于在malloc的数组上写了外部内存,我无法找到错误的位置。
以下是代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define A(i,j) aa[m*(j)+(i)] //matrix by columns
#define B(i,j) bb[n*(j)+(i)]
#define C(i,j) cc[m*(j)+(i)]
void mmul (int m, int n, double *aa, double *bb, double *cc) {
int i, j, k;
for (i=0; i<m; i++)
for (j=0; j<m; j++) {
C(i,j)=0;
for (k=0; k<n; k++) C(i,j)+=A(i,k)*B(k,j);
}
}
int main (int argc, char *argv[]) {
clock_t exec_timer=clock(), comp_timer;
srand(time(NULL)); //initialize random seed
int m, n, i;
double *aa, *bb, *cc, exec_time, comp_time;
if (argc!=3
|| sscanf(argv[1], "%d", &m)!=1
|| sscanf(argv[2], "%d", &n)!=1
) {
fprintf(stderr, "%s m n \n", argv[0]);
return -1;
}
/* malloc memory */
aa=malloc(m*n*sizeof(int)); //integer matrix
bb=malloc(n*m*sizeof(int));
cc=malloc(m*m*sizeof(int));
/* fill matrix */
for (i=0; i<m*n; i++) aa[i]=rand()%10; //fill with random integers 0-9
for (i=0; i<n*m; i++) bb[i]=rand()%10;
/* compute product */
comp_timer=clock();
mmul(m,n,aa,bb,cc);
comp_time=(double) (clock() - comp_timer) / CLOCKS_PER_SEC;
/* write output */
for (i=0; i<m*m; i++) printf("%i\n",cc[i]);
/* finishing */
free(aa); free(bb); free(cc);
exec_time=(double) (clock() - exec_timer) / CLOCKS_PER_SEC;
printf("exec time = %.3f, comp = %.3f\n", exec_time, comp_time);
return 0;
}
#undef C
#undef B
#undef A
任何人都可以看到我遗漏的问题?
答案 0 :(得分:4)
嗯,是的,我可以看到问题。
您正在使用double
数组,但您的分配代码使用int
。由于double
的大小通常是int
的两倍,因此会导致大量的缓冲区溢出,从而导致随机内存无法使用。
基本上,这个:
aa=malloc(m*n*sizeof(int)); //integer matrix
撒谎。 :)它应该是:
aa = malloc(m * n * sizeof *aa); /* Not an integer matrix! aa is double *. */
当然,bb
和cc
的分配也是如此。
注意使用sizeof *aa
(意思是“指针aa
指向的值的大小”)来消除引入此错误的风险,即不通过手动重复类型而是“将它“锁定到实际指针,使代码更安全。
作为次要说明,与问题无关,您应该使用const
作为mmul()
的只读参数,如下所示:
void mmul (int m, int n, const double *aa, const double *bb, double *cc)
这会立即显示哪些指针是输入,哪些是输出。它还可以帮助编译器生成更好的代码,但主要优点是它可以更清楚地传达您的意思。