C структура для динамического 2d массива: ошибка для объекта 0x7ffeee94ab80: освобожденный указатель не был выделен - PullRequest
0 голосов
/ 14 декабря 2018

Я использую clang-1000.11.45.5 на MacBook.Я пытаюсь создать структуру для динамически размещаемой 2D-матрицы.Это выглядит так:

typedef struct
{
    int m_rows;
    int m_cols;
    double **arr;
    double *data;
} t_mtrx;

t_mtrx *init_mtrx(int rows, int cols)
{
    t_mtrx *A = malloc(sizeof(t_mtrx));
    A -> m_rows = rows;
    A -> m_cols = cols;
    A -> arr = malloc(rows * sizeof(*A->arr));
    A -> data = malloc(rows * cols * sizeof(*A->data));

    for(int i = 0; i < rows; i++, A -> data += cols)
        A -> arr[i] = A -> data;

    return A;
}

void del_mtrx(t_mtrx *A)
{
    free(A->data);
    free(A->arr);
}

В основном в каждой матрице есть два указателя:

*data: все элементы в матрице расположены в одномерном массиве

**arr: указатели на адрес первого элемента каждого столбца

С этим все работало нормально, кроме создания деконструктора.

int main()
{
    int rows = 3;
    int cols = 3;

    double ra[] = {1, 3223, 5},
           rb[] = {2, 0, -99},
           rc[] = {14, 134, 130};

    t_mtrx A = *init_mtrx(rows, cols);

    A.arr[0] = ra;
    A.arr[1] = rb;
    A.arr[2] = rc;

    print_mtrx(&A);

    del_mtrx(&A);

}

Когда я запускаю это, все работает, кроме del_mtrx.

$ ./a.out 

[[   1.00, 3223.00,    5.00],
 [   2.00,    0.00,  -99.00],
 [  14.00,  134.00,  130.00]] 3 x 3
a.out(684,0x10533e5c0) malloc: *** error for object 0x7fea65c02a48: pointer being freed was not allocated
a.out(684,0x10533e5c0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6

Я знаю, что проблема с free(A -> data);, потому что, когда я комментирую это, нетошибка, но я не уверен, как еще ее освободить.

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

В коде есть два недостатка

  • Цикл for меняет значение A->data.Измененный A->data не может быть передан в free, так как он больше не указывает на начало блока памяти.
  • Сама структура не освобождается, что приводит к утечке памяти.Простое правило управления памятью состоит в том, что каждый malloc должен иметь соответствующий free.

Устранить вторую проблему просто, просто free(A) в функции del_mtrx.Первая проблема может быть исправлена, как показано в коде ниже.Обратите внимание, что адреса, назначенные ему A->arr, одинаковы, но A->data не изменяется.

t_mtrx *init_mtrx(int rows, int cols)
{
    t_mtrx *A = malloc(sizeof(t_mtrx));
    A->m_rows = rows;
    A->m_cols = cols;
    A->arr = malloc(rows * sizeof(*A->arr));
    A->data = malloc(rows * cols * sizeof(*A->data));

    for(int i = 0; i < rows; i++)
        A->arr[i] = A->data + (i * cols);

    return A;
}

void del_mtrx(t_mtrx *A)
{
    free(A->data);
    free(A->arr);
    free(A);
}

Есть также две проблемы в main

  • Указательвозвращаемый init_mtrx не должен разыменовываться, а просто использоваться как есть.Разыменование указателя делает ненужную копию структуры и создает утечку памяти.
  • При назначении массивов указатели перезаписываются, что делает A->data совершенно неактуальным.

ВотПример реализации для main, который копирует данные в выделенную память.Обратите внимание, что если вы не хотите копировать данные, то функция init_mtrx не должна выделять память для A->data.

int main(void)
{
    int rows = 3;
    int cols = 3;

    double ra[] = {1, 3223, 5},
           rb[] = {2, 0, -99},
           rc[] = {14, 134, 130};

    t_mtrx *A = init_mtrx(rows, cols);

    memcpy(A->arr[0], ra, sizeof(ra));
    memcpy(A->arr[1], rb, sizeof(rb));
    memcpy(A->arr[2], rc, sizeof(rc));

    print_mtrx(A);

    del_mtrx(A);
}
0 голосов
/ 14 декабря 2018

Ваши A-> данные при возврате из функции больше не указывают на начало выделенной памяти

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...