繁体   English   中英

打印矩阵导致分段错误

[英]Printing a matrix causes a segmentation fault

我试图根据这段代码打印一个矩阵,但不知何故它导致了分段错误。 我想将给定的 arrays 传输到结构成员数据,然后通过引用数据打印出来。 我扫描了它,但找不到我的错误。 也许我在为结构分配 memory 时搞砸了。

#include "base.h"

struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows; a row is an array of n_cols doubles 
};
typedef struct Matrix Matrix;

Matrix* make_matrix(int n_rows, int n_cols) {
    Matrix* mat = xcalloc(n_rows,sizeof(double*));
    mat->rows = n_rows;
    mat->cols = n_cols;
    return mat;
}

Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    Matrix* mat = make_matrix(n_rows, n_cols);
    for(int i = 0; i < (mat->rows); i++)
    {
        for(int j = 0; j < (mat->cols); j++)
        {
            mat->data[i][j] = data[i] + j;
        }
    }
    return mat;
}

void print_matrix(Matrix* m)
{
    for(int i = 0; i < (m->rows); i++)
    {
        for(int j = 0; j < (m->cols); j++)
        {
            printf("%g", m->data[i][j]);
        }
    }
}

void matrix_test(void) {
    double a[] = { 
        1, 2, 3, 
        4, 5, 6, 
        7, 8, 9 };
    Matrix* m1 = copy_matrix(a, 3, 3);
    print_matrix(m1);

    double a2[] = { 
        1, 2, 3, 
        4, 5, 6 };
    Matrix* m2 = copy_matrix(a2, 2, 3);
    print_matrix(m2);

    double a3[] = { 
        1, 2, 
        3, 4, 
        5, 6 };
    Matrix* m3 = copy_matrix(a3, 3, 2);
    print_matrix(m3);
}

在这个特定的示例中,没有明显的理由说明您应该动态分配结构本身,因为它只有 3 个项目。 因为这是完全错误的:

Matrix* mat = xcalloc(n_rows,sizeof(double*));

要么必须分别为结构及其指针数组分配空间,要么可以跳过结构的动态分配,然后只为数据成员分配空间。

此外xcalloc(n_rows,sizeof(double*)); 只为指针数组分配空间,而不是那些指针指向的空间。 因此,您还需要在单独的循环中为每个数据项分配空间。

此外,对矩阵使用指针数组几乎可以肯定是不必要的晦涩和低效的做法。 相反,您应该使用二维数组,如下所示: Correctly allocating multi-dimensional arrays

您还应该 free() 所有分配的 memory。


这是一个清理过的示例,其中我将指向指针的指针替换为所谓的“灵活数组成员”。 这具有将结构与数据一起分配以加快访问速度的优点。 分散分配的所有问题也将消失。

不利的一面是灵活的数组成员必须被视为平面一维数组,因此我们必须在使用array[i][j]语法之前转换为指向二维数组类型的指针。

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    size_t rows;
    size_t cols;
    double data[];
} Matrix;

Matrix* make_matrix (size_t n_rows, size_t n_cols) {
    Matrix* mat = malloc(sizeof(Matrix) + sizeof(double[n_rows][n_cols]));
    if(mat == NULL)
    {
        return NULL;
    }

    mat->rows = n_rows;
    mat->cols = n_cols;
    return mat;
}

Matrix* copy_matrix (const double* data, size_t n_rows, size_t n_cols) {
    Matrix* mat = make_matrix(n_rows, n_cols);
    double (*new_data)[mat->cols];
    new_data = (double(*)[mat->cols]) mat->data;

    for(size_t i = 0; i < mat->rows; i++)
    {
        for(size_t j = 0; j < mat->cols; j++)
        {
            new_data[i][j] = data[i] + j;
        }
    }
    return mat;
}

void print_matrix (const Matrix* mat)
{
    double (*data)[mat->cols];
    data = (double(*)[mat->cols]) mat->data;

    for(size_t i = 0; i < mat->rows; i++)
    {
        for(size_t j = 0; j < mat->cols; j++)
        {
            printf("%g ", data[i][j]);
        }
        printf("\n");
    }
}

int main (void) {
    double a[] = { 
        1, 2, 3, 
        4, 5, 6, 
        7, 8, 9 };
    Matrix* m1 = copy_matrix(a, 3, 3);
    print_matrix(m1);
    puts("");

    double a2[] = { 
        1, 2, 3, 
        4, 5, 6 };
    Matrix* m2 = copy_matrix(a2, 2, 3);
    print_matrix(m2);
    puts("");

    double a3[] = { 
        1, 2, 
        3, 4, 
        5, 6 };
    Matrix* m3 = copy_matrix(a3, 3, 2);
    print_matrix(m3);

    free(m1);
    free(m2);
    free(m3);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM