C - 矩阵乘法分段错误

Posted

技术标签:

【中文标题】C - 矩阵乘法分段错误【英文标题】:C - matrix multiplication segmentation fault 【发布时间】:2012-03-29 14:01:00 【问题描述】:

运行此代码时出现分段错误。有谁知道为什么?谢谢。

#include <stdio.h>

int main()

    double **m1, **m2, **mr;
    int m1_rows, m1_cols, m2_rows, m2_cols, mr_rows, mr_cols;
    int i, j, k;

    printf("Enter number of rows for matrix 1: ");
    scanf("%d", &m1_rows);

    printf("Enter number of columns for matrix 1: ");
    scanf("%d", &m1_cols);

    printf("Enter number of rows for matrix 2: ");
    scanf("%d", &m2_rows);

    printf("Enter number of columns for matrix 2: ");
    scanf("%d", &m2_cols);

    //allocate memory for matrix 1 m1
    m1 = (double **) calloc(m1_rows, sizeof(double *));
    for (i = 0; i < m1_rows; i++) 
        m1[i] = (double *) calloc(m1_cols, sizeof(double));
    

    //allocate memory for matrix 2 m2
    m2 = (double **) calloc(m2_rows, sizeof(double *));
    for (i = 0; i < m2_rows; i++) 
        m2[i] = (double *) calloc(m2_cols, sizeof(double));
    

    //allocate memory for sum matrix mr
    mr = (double **) calloc(mr_rows, sizeof(double *));
    for (i = 0; i < mr_rows; i++) 
        mr[i] = (double *) calloc(mr_cols, sizeof(double));
    

    //assign  mr_rows and mr_cols
    mr_rows = m1_rows;
    mr_cols = m2_cols;

    //initialize product matrix
    for (i = 0; i < m1_rows; i++) 
        for (j = 0; j < m2_cols; j++) 
            mr[i][j] = 0;
        
    

    //perform matrix multiplication
    for (i = 0; i < m1_rows; i++) 
        for (j = 0; j < m2_cols; j++) 
            mr[i][j] = 0;
            for (k = 0; k < m1_cols; k++) 
                mr[i][j] += m1[i][k] * m2[k][j];
            
        
    

    //print result
    for (i = 0; i < mr_rows; i++) 
        for (j = 0; j < mr_cols; j++) 
            printf("%f\t", mr[i][j]);
        
    

    //free memory m1
    for (i = 0; i < m1_rows; i++); 
        free(m1[i]);
    
    free(m1);

    //free memory m2
    for (i = 0; i < m2_rows; i++); 
        free(m2[i]);
    
    free(m2);

    //free memory mr
    for (i = 0; i < mr_rows; i++); 
        free(mr[i]);
    
    free(mr);

    return 0;

我使用 valgrind valgrind --tool=memcheck a.out 运行以获取有关分段错误的更多信息,但结果超过 30000 个错误,因此没有打印出来。

【问题讨论】:

在 GDB 中运行它以识别行。然后修复它。然后修复 30000 Valgrind 错误。然后继续开发。 @OliCharlesworth 其实我建议先阅读代码来调试它。这应该始终是方法的第一线,而不是使用工具。这样才能获得洞察力。 @DavidHeffernan:也许在一个 30 行的应用程序上。我不会目视检查 10000 行代码库来找出发生段错误的位置...... @OliCharlesworth 不,当然不是。我想我正专注于这个特定的问题。 【参考方案1】:

您没有分配mr_rowsmr_cols。它们需要像这样设置:

mr_rows = m1_rows;
mr_cols = m2_cols;

这条线不好:

mr[i][j] += m1[i][k] * m2[k][j];

这将是越界访问元素,尤其是因为k 未初始化。您需要在三个嵌套的 for 循环中使用该代码行。实际上,您也可以将归零代码也滚入其中。

for(i=0; i<m1_rows; i++)
    for(j=0; j<m2_cols; j++)
        mr[i][j] = 0;
        for(k=0; k<m1_cols; k++)
            mr[i][j] += m1[i][k]*m2[k][j];
        
    

另外,你所有的内存释放循环都是错误的。而不是

for(i=0; i<m1_rows; i++);
    free(m1[i]);

free(m1);

它应该是

for(i=0; i<m1_rows; i++)
    free(m1[i]);

free(m1);

那个杂乱无章的分号要了你的命。

您还需要检查m1 中的列数是否等于m2 中的行数,即测试m1_cols == m2_rows

最后一点。你在这里可怕地复制了你的代码。不要有三个相同的 for 循环来分配矩阵和三个相同的 for 循环来释放。将这些操作提取到可以从main 调用的辅助函数中。

我能找到的就这些了!

【讨论】:

我仍然遇到分段错误。我还没有添加针对 m2 行检查 m1 cols 的测试,但是我使用 m1 2x2 和 m2 2x2 进行了测试,所以它应该可以正常工作。我更新了我的代码。 您必须先分配给mr_rowsmr_cols,然后才能使用它们!! 您需要修复释放内存的代码。一个杂散的分号。【参考方案2】:

您没有在任何地方为mr_rows and mr_cols 分配任何值。所以它们会有垃圾值,你可以通过调用calloc().来使用它们来分配内存

【讨论】:

以上是关于C - 矩阵乘法分段错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 AVX 的平铺矩阵乘法

犰狳 - 矩阵乘法错误

矩阵的乘法运算怎么算?

C语言实现矩阵乘法

min 与 + 运算转换成类似于矩阵乘法的推导过程

矩阵的乘法运算法则