【问题标题】:C dynamically allocated struct object causes runtime error ("Segmentation fault (core dumped)")C 动态分配的结构对象导致运行时错误(“分段错误(核心转储)”)
【发布时间】:2020-01-18 16:03:13
【问题描述】:
struct matrix {
    int m, n;   // m rows, n columns
    int** data;
    char name[64];
};

struct matrix* alloc_matrix(const char* name, int m, int n) {
    struct matrix *mat = malloc(sizeof(struct matrix));
    strcpy(mat->name, name);
    mat->m = m;
    mat->n = n;
    mat->data = (int**)malloc(sizeof(m) * (m * n));
    return mat;
}

int main() {
    struct matrix* mat1 = alloc_matrix("mat1", 4, 4);
    mat1->data[0][0] = 2;    <------------------------------ This line causes the error
    return EXIT_SUCCESS;
}

所以我想实现矩阵。我定义了一个结构矩阵,其中包含一个矩阵的名称、行数、列数和数据。使用函数 alloc_matrix 我想​​为结构对象分配内存。但是这个函数出了点问题,因为如果我想在分配的对象上检索或设置数据,我会得到一个运行时内存错误。

希望有人对动态数据分配有更多经验并看到问题。

【问题讨论】:

    标签: c malloc


    【解决方案1】:

    data 被用作二维数组。也就是说,它是一个数组,其中数组的每个元素本身就是一个整数数组。

    mat->data = (int**)malloc(sizeof(m) * (m * n));
    

    这一行分配第一个数组。它现在有足够的空间来容纳 m*n 指针,但指针不指向任何东西。这不是你想要的。

    你想要的是数据保存 m 个指针,每个指针保存 n 个元素。

    mat->data = (int**)malloc(sizeof(*mat->data) * m);
    
    if(!mat->data)
    {
        //handle error case
    }
    
    for(int ii = 0; ii < m; ++ii)
    {
        mat->data[ii] = (int*)malloc(sizeof(**mat->data) * n);#
    
        if(!mat->data[ii])
        {
             //handle error case
        }
    }
    

    【讨论】:

    • 尽可能使用对象而不是 sizeof 中的类型。这是一个很好的做法
    • 谢谢!对于其他想知道的人,this question 解释了为什么我们可以在 malloc 之前取消引用它们。
    • 我们不会取消引用它们。 sizeof 发生编译时间
    • 抱歉,我的评论措辞不当。最初我对看起来像是一种尊重感到惊讶,直到我记得 sizeof 是编译时间。我链接到问题以向其他同样惊讶的人解释。我会按照你的建议添加错误检查。
    【解决方案2】:

    mat-&gt;data = (int**)malloc(sizeof(m) * (m * n)); 这行不符合你的想法。您需要先为指针分配空间,然后为所有已分配指针的引用对象分配空间。

    重要!!!您需要始终检查 malloc 的结果!

    必须是:

        if(mat->data = malloc(sizeof(*mat->data) * (m)))
        {
            for(size_t index = 0; index < n; index++)
            {
                if(!(mat->data[index] = malloc(sizeof(**mat->data) * n)))
                {
                    //do something if malloc failed
                }
            }
        }
    

    https://godbolt.org/z/skBJzb

    在这种情况下,我个人不会这样做。我个人更喜欢限制 malloc 的数量

    struct matrix {
        size_t r, c;   // r rows, c columns
        char name[64];
        int data[];
    };
    
    struct matrix* alloc_matrix(const char* name, size_t rows, size_t cols) {
        struct matrix *mat = malloc(sizeof(*mat) + rows * cols * sizeof(mat -> data[0]));
        if(mat)
        {
            strcpy(mat->name, name);
            mat->r = rows;
            mat->c = cols;
        }
        return mat;
    }
    
    int setdata(struct matrix *mat, size_t row, size_t col, int val)
    {
        int result = -1;
        
        if(mat)
        {
            if(row < mat -> r && col < mat -> c)
            {
                mat -> data[row * mat -> c + col] = val;
                result = 0;
            }
        }
        return result;
    }
    
    
    int main() {
        struct matrix* mat1 = alloc_matrix("mat1", 4, 4);
        
        if(mat1)
        {
            printf("set result %d\n", setdata(mat1, 2, 2, 0));
            printf("set result %d\n", setdata(mat1, 5, 2, 0));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-23
      • 2020-07-17
      • 2022-01-02
      • 2021-10-19
      • 1970-01-01
      相关资源
      最近更新 更多