Повторно добавить один элемент в список динамических массивов (после удаления его из памяти) - PullRequest
0 голосов
/ 24 апреля 2019

Я работаю над списками динамических массивов в c.У меня возникают некоторые проблемы, когда я пытаюсь повторно добавить один элемент в один массив после освобождения.

Структура:

typedef struct array_list{
    void** array;
    size_t size;
    size_t capacity;
}array_list_t;

Метод свободного массива:

void* array_list_free(array_list_t* array) {
    free(array->array);
    free(array);
    array->capacity = 0;
    array->size = 0;
    array->array = NULL;
}

Распределить и перераспределить метод:

void array_list_check_and_realloc(array_list_t* array) {
    if(!(array->capacity > array->size)) {
        if(array->capacity == 0){
            //the problem is probably here
            array->capacity++;
            array->array = realloc(array->array, sizeof(void*) * array->capacity);
        }else{
            array->capacity *= 2;
            array->array = realloc(array->array, sizeof(void*) * array->capacity);
        }
    }
}

Вставить элемент в массив:

void* array_list_insert(array_list_t* array, void* element) {
    array_list_check_and_realloc(array);
    size_t i;
    for( i = array_list_size(array); i > 0; --i ) {
        array->array[i] = array->array[i-1];
    }
    array->array[i] = element;
    array->size += 1;
}

Main:

    array_list_insert(array,8);
    array_list_free(array);
    array_list_insert(array,8); // <--- Segmentation Fault

Когда я пытаюсь запустить программу, у меня естьНет ошибки терминала и, кажется, работает нормально.Но когда я пытаюсь использовать отладчик, я вижу ошибку сегментации, и я не знаю, почему (я использую CLion IDE) извините, я новичок в языке c ^^ '

Ответы [ 3 ]

1 голос
/ 24 апреля 2019

Большая проблема здесь:

void* array_list_free(array_list_t* array) {
    free(array->array);
    free(array);   
    array->capacity = 0;  //<<< oups, array points nowhere here as it has been
    array->size = 0;      //    freed on the previous line....
    array->array = NULL;
}

удалить три строки, начинающиеся с array->, из функции.

1 голос
/ 24 апреля 2019

Без минимально скомпилируемого проверяемого примера , включенного в ваше сообщение, это будет ограничено общими предложениями:

Одна потенциальная проблема заключается в том, что прототип:

void array_list_check_and_realloc(array_list_t* array);

Необходимо изменить, чтобы разместить указатель на объект, который должен быть выделен в памяти:

void array_list_check_and_realloc(array_list_t **array) 

Это грубое желание также изменит способ его вызова и код внутри него.function.

Некоторые комментарии к именованию:
Используемая структура включает имя члена array.Следующие прототипы также включают в себя экземпляр аргумента всей структуры с именем array.:

void* array_list_free(array_list_t* array);
void array_list_check_and_realloc(array_list_t* array); 

Хотя это допустимо, это может сбивать с толку.

Использование постфикса _t для обозначения вашей структуры array_list_t также не рекомендуется по причинам, объясненным здесь .

Некоторые комментарии кВаша структура struct:

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

Например, рассмотрите возможность изменения исходной структуры из этого:

typedef struct array_list{
    void** array;
    size_t size;
    size_t capacity;
}array_list_t;

на что-то более похожее на это: (включает исключение '_t'постфикс из имени typedef.)

typedef struct array_list{
    size_t size;
    size_t capacity;
    struct array_list *array //this becomes new nodes of your list. 
}ListNode;
1 голос
/ 24 апреля 2019

Проблема (по крайней мере, проблема ) заключается в том, что array_list_free освобождает сам объект array_list_t, а не только внутренний динамический массив:

    free(array);

Если это не проблемасамо по себе (что происходит, если этот объект не был динамически размещен), тогда проблема заключается в том, чтобы продолжать использовать этот объект впоследствии, не выделяя для него новое пространство и не инициализируя это пространство - как в самой этой функции, так и после ее возврата.

Говоря об инициализации, функция инициализации отличается отсутствием среди тех, кого вы представляете.Возможно, вы инициализируете свои объекты с помощью обычных инициализаторов или инициализации по умолчанию, или, возможно, вы просто опустили функцию, но помните, что вы не должны полагаться на неинициализированные объекты.

...