【问题标题】:Matrix multiplication dynamically allocated matrix error: segmentation fault (core dump)矩阵乘法动态分配矩阵错误:分段错误(核心转储)
【发布时间】:2013-04-05 01:20:51
【问题描述】:

我正在写一个矩阵乘法程序,我需要检查不同大小的不同矩阵的运行时间。然后我需要将我的代码与 main 中的 pthread 并行化,因此我创建了一个头文件,其中包括初始化和乘法函数,然后我的 main 在一个单独的 .c 文件中,但是当我执行我的程序时,我得到以下错误:

错误:分段错误(核心转储)

请注意,我正在尝试对大小为 1000 的方阵进行矩阵乘法。

这是我的代码:

// mm.h

#ifndef MM_H
#define MM_H

#include <stdlib.h>
#include <time.h>

int SIZE, NTHREADS;
int **A, **B, **C;

void init(int **A, int **B, int **C)
{
    int i, j;

    A = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        A[i] = malloc(SIZE * sizeof(int));

    B = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        B[i] = malloc(SIZE * sizeof(int));

    C = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        C[i] = malloc(SIZE * sizeof(int));

    srand(time(NULL));

    for(i = 0; i < SIZE; i++) {
        for(j = 0; j < SIZE; j++) {
            A[i][j] = rand()%100;
            B[i][j] = rand()%100;
        }
    }
}

void mm(int **A, int **B, int **C)
{
    int i, j, k;

    for(i = 0; i < SIZE; i++) {
        for(j = 0; j < SIZE; j++) {
            C[i][j] = 0;
            for(k = 0; k < SIZE; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}

#endif

任何我的主要功能:

// mmserial.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mm.h"

int main(int argc, char* argv[])
{
    int i;

    if(argc != 2)
    {
        printf("Usage: %s <size_of_square_matrix>\n", argv[0]);
        exit(1);
    }

    SIZE = atoi(argv[1]);
    init(A, B, C);

    clock_t begin, end;
    double time_spent;

    begin = clock();

    mm(A, B, C);

    end = clock();

    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;

    printf("Elapsed time: %.2lf seconds.\n", time_spent);

    for(i = 0; i < SIZE; i++)
        free((void *)A[i]);
    free((void *)A);

    for(i = 0; i < SIZE; i++)
        free((void *)B[i]);
    free((void *)B);

    return 0;
}

如果有人可以帮助我解决这个问题,我会很高兴。还有更多的问题,我是否也应该动态分配我的最终矩阵,它将保存乘法的结果值?

【问题讨论】:

  • 您应该在代码中指出您收到错误的确切行。另外,我建议删除time 标签,而是添加CC++
  • @Axel 感谢您的建议。我编辑了它。我得到一个分段错误错误,所以它不在代码的特定位置,但我猜它与动态分配的矩阵有关。
  • 在写入之前您没有检查 malloc() 的结果。
  • 在这种情况下,您应该在启用调试信息的情况下进行编译并从调试器中运行您的程序以找出崩溃发生的位置。

标签: c memory time matrix dynamic-allocation


【解决方案1】:

我一直在寻找最终代码,但没有可用的更新,对于那些对动态分配矩阵乘法感兴趣的人,这里是最终代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void allocate_mem(double*** arr, int rows, int cols);
void deallocate_mem(double*** arr, int n);
void printMatrix(double** a, int rows, int cols);
void printMatrixE(double** a, int rows, int cols);
void multMatrixp(double **A, double **B, double **C,int r1,int c1,int r2,int c2);
void init(double*** a, int rows,int cols);

int main(int argc, char* argv[])
{

   int ro1, co1, ro2, co2;
   double **a, **b, **c;    



//ro1=10;
//co1=10000;
//ro2=10000;
//co2=33;

ro1=atoi(argv[1]);
co1=atoi(argv[2]);
ro2=atoi(argv[3]);
co2=atoi(argv[4]);


init(&a,ro1,co1);
init(&b,ro2,co2);
allocate_mem(&c,ro1,co2);

clock_t begin, end;
double time_spent;
begin = clock();
multMatrixp(a, b, c, ro1, co1, ro2, co2);  
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Elapsed time: %.2lf seconds.\n", time_spent);

printMatrix(a,ro1,co1); 
printMatrix(b,ro2,co2); 
printMatrixE(c,ro1,co2); 


deallocate_mem(&a,ro1);
deallocate_mem(&b,ro2);
deallocate_mem(&c,ro1);

    return 0;
}

//______________________________________________________________________________
void allocate_mem(double*** arr, int rows, int cols)
{
  int i;
  *arr = (double**)malloc(rows*sizeof(double*));
  for( i=0; i<rows; i++)
    (*arr)[i] = (double*)malloc(cols*sizeof(double));
} 

//______________________________________________________________________________
void deallocate_mem(double*** arr, int rows){
 int i;
    for (i = 0; i < rows; i++)
        free((*arr)[i]);
    free(*arr); 
}

//______________________________________________________________________________

void init(double*** a, int rows,int cols)
{
   int i, j;

*a= (double**) malloc(rows*sizeof(double*));
for(i=0;i<rows;i++)
(*a)[i]=(double*)malloc(cols*sizeof(double));
    for(i=0;i<rows;i++)
        for(j=0;j<cols;j++)
        (*a)[i][j] = rand()%1000;
}


//______________________________________________________________________________
void printMatrix(double** a, int rows, int cols)
{
    int i, j;
   printf("Matrix[%d][%d]\n",rows,cols);    
   for(i=0;i<rows;i++){
      for(j=0;j<cols;j++)
      printf("%7.1lf ",a[i][j]);
      printf("\n");
   }
   printf("\n");   
}

//______________________________________________________________________________
void printMatrixE(double** a, int rows, int cols)
{
    int i, j;
   printf("Matrix[%d][%d]\n",rows,cols);    
   for(i=0;i<rows;i++){
      for(j=0;j<cols;j++)
      printf("%9.2e ",a[i][j]);
      printf("\n");
   } 
   printf("\n");     
}


//______________________________________________________________________________

void multMatrixp(double **A, double **B, double **C,int ro1,int co1,int ro2,int co2)
{
    int i, j, k;
    for(i = 0; i < ro1; i++) {
        for(j = 0; j < co2; j++) {
            C[i][j] = 0;
            for(k = 0; k < co1; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    您的代码存在多个问题。以下是您的程序中遇到的问题的解决方案。

    首先,您需要为C 数组分配空间。 tacp 已经涵盖了这一点,因此,我将跳过相同的内容。

    主要问题来自init(A,B) 函数。这里有几个问题。一,AB 是全局指针,因此实际上不需要作为函数参数传递。但是,由于您的代码是为此而设计的,因此您必须合并以下更改

    //main function invoking init
    init(&A, &B); // Pass references to A and B
    

    init的脚印需要修改为

    void init(int ***Aptr, int ***Bptr)
    {
         int    **A; // Define a local pointer to keep rest of the code intact
         int    **B; // Define a local pointer to keep rest of the code intact
         .....................
         //Rest of your code
    
         // End of function
         *Aptr = A;
         *Bptr = B;
    }
    

    通过这 2 项更改,您的代码应该可以正常工作了。在您之前的实现中,init 函数中仅更新了 AB 的本地副本,并且未反映在实际指针上。因此,当init 完成时,AB 指向潜在的NULL 指针,这是导致分段错误的原因。

    这个问题有另一种解决方案。您可以避免将参数传递给init,即将init 转换为init() 并将实现修改为void init()。这可以正常工作(再次假设 C 也已分配)

    但是,还有一点。 最后,您还需要注意删除C 数组的内存(假设它是在init 函数中分配的)

    for(i = 0; i < SIZE; i++)
        free((void *)C[i]);
    free((void *)C);
    

    后记:

    从编程的角度来看,我觉得你不应该混合全局变量并将这些非常全局的变量作为函数参数传递。范围是全局的,这意味着函数绝对可以访问变量,因此不需要将相同的变量传递给函数。

    【讨论】:

      【解决方案3】:

      C 也是一个动态矩阵,但你从来没有为它分配内存,直接将值分配给不存在的内存,所以这就是你有核心转储的原因。您还应该为C 分配内存。

       void mm(int **A, int **B, int **C)
       {
         int i, j, k;
      
         for(i = 0; i < SIZE; i++) {
            for(j = 0; j < SIZE; j++) {
              C[i][j] = 0;   ///^^^Need to first allocate space for C
              for(k = 0; k < SIZE; k++) {
                  C[i][j] += A[i][k] * B[k][j];
              }
            }
         }
      }
      

      【讨论】:

      • 已发布,不便之处敬请见谅。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多