C динамически размещаемый объект структуры вызывает ошибку во время выполнения («Ошибка сегментации (дамп памяти)») - PullRequest
0 голосов
/ 18 января 2020
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;
}

Итак, я хочу реализовать матрицы. Я определил структурную матрицу, которая содержит имя, количество строк, количество столбцов и данные matix. С помощью функции alloc_matrix я хочу выделить память для объекта struct. Но что-то не так в этой функции, потому что, если я хочу получить или установить данные для выделенного объекта, я получаю ошибку памяти времени выполнения.

Я надеюсь, что кто-то имеет больше опыта с динамическим c распределением данных и видит проблема.

Ответы [ 2 ]

2 голосов
/ 18 января 2020

данные используются в качестве двумерного массива. То есть это массив, в котором каждый элемент массива представляет собой массив целых чисел.

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
    }
}
2 голосов
/ 18 января 2020

mat->data = (int**)malloc(sizeof(m) * (m * n)); эта строка не делает то, что вы думаете. Вам нужно сначала выделить c пробел для указателей, а затем пробел для ссылочных объектов для всех выделенных указателей.

важно !!! Вам всегда нужно проверять результат работы mallo c!

, он должен быть:

    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));
    }
}

...