Общая функция для освобождения двумерных массивов с атрибутом очистки в C - PullRequest
0 голосов
/ 20 ноября 2018

Я недавно обнаружил __attribute__((cleanup)), что очень удобно.Я сделал универсальную функцию, чтобы освободить любой тип указателя, и она отлично работает.

#define _autofree_ __attribute__ ((cleanup(free_pointer)))

...

void free_pointer(void *pointer)
{
    free(*(void **) pointer);
}

Но это не так просто, когда дело доходит до освобождения 2D-массивов.Насколько я знаю, очистка использует указатель на данный указатель для ограничения стека, и это хорошо, потому что она не использует копию в любой точке.В любом случае, разыменование (void **) приведения для прохождения ошибок «разыменование void *» работает, но тогда, если я делаю

#define _autofree2d_ __attribute__ ((cleanup(free_pointer_array)))

...

void free_pointer_array(void *pointer_array)
{
    for (size_t i = 0 ; (void **) pointer_array[i] ; ++i)
        free(*(void **) pointer_array[i]);
    free(*(void ***) pointer_array);
}

, я получаю разыменование void * из-за скобок [i].Кроме того, это просто не выглядит правильно.

Я также пытаюсь сделать это менее универсальным способом, используя указатели на символы (как я сейчас работаю с массивом слов), и он компилируется, но дает нам segfaultиз-за недействительного свободного.

void free_pointer_array(char ***array)
{
    for (size_t i = 0 ; *array[i] ; ++i)
        free(*array[i]);
    free(**array);              // Tried using ***array and got
                                // "pointer from integer without a cast" error
}

1 Ответ

0 голосов
/ 21 ноября 2018

Как упомянул Эндрю Хенле в комментариях, мой метод распределения был проблемой.Я делал справочную таблицу , а не фактический 2d массив.Используя описанный здесь метод: Правильно выделяя многомерные массивы , я могу просто использовать свой оригинальный макрос _autofree_ для массивов любого измерения.

...