Страницы

Поиск по вопросам

среда, 1 января 2020 г.

Обертка над realloc

#c #инспекция_кода #memory #realloc


Написал свою обертку над realloc. Все ли здесь правильно? Может быть есть какие-то
недочеты, которых я не заметил?

#define qk_realloc(p, n) qk_realloc__(p, &p, n)

/*
=================================
[TEST] The qk_realloc__ function

Функция изменяет размер блока памяти,
на который указывает old. Если операция
выполнена успешно, то old присваивается
адрес нового блока памяти. Если операция
не выполнилась, в куче выделяется НОВЫЙ
блок памяти, в него копируется содержимое
old, старые данные освобождаются и указателю
old присваевает адрес нового блока памяти.
Если память не может быть выделена и для
нового блока, функция возвращает NULL,
при этом входные данные не изменяются.
=================================
*/

void* qk_realloc__(void* old, void* const ptrToOld, const u32 n) {
    void* new = realloc(old, n);

    if (new != NULL) {
        return *((void**) ptrToOld) = new;
    }

    // Тут должно быть сообщение типа: "не удалось выполнить realloc(n)".

    new = qk_malloc(n);

    if (new != NULL) {
        memmove(new, old, n);
        free(old);
        return *((void**) ptrToOld) = new;
    }

    // И тут похожее сообщение...

    return NULL;
}

    


Ответы

Ответ 1



Логика разработчика этой оболочки совершенно не ясна Зачем в функцию передается одновременно old и указатель на old (ptrToOld)? Если уж вы хотите передавать ptrToOld, то по нему можно получить и значение old. Зачем передавать old отдельно? Почему делается безусловное memmove(new, old, n);? А если новый размер больше старого? Также стандартный realloc разрешает передавать ему на вход нулевой указатель. Ваш memmove не учитывает эту возможность. Почему ptrToOld имеет такой странный тип - void* const? Почему этот тип не является указателем на указатель? Почему вы решили, что после неудачи realloc вы сможете сделать malloc? Теоретически, неудачи у realloc могут быть разные, но мы-то понимаем, что практически всегда неудача realloc - это просто нехватка памяти. Почему вы считаете, что если realloc не смог выделить память, то malloc сможет? *((void**) ptrToOld) - переинтрепретация памяти, возможно нарушение strict-aliasing. Почему memmove, а не memcpy? И чего именно вы пытались добиться? Первая мысль была в том, что эта оболочка призвана бороться с недостатками варианта p = realloc(p, ...), но она с ними никак не борется. Так в чем же тогда смысл?

Ответ 2



Все ли здесь правильно? Всё неправильно. Начиная с того, что нет никакой нужды делать обёртки над хорошо себя зарекомендовавшими стандартными функциями. Я даже не буду смотреть в ваш код, ответьте на простой вопрос: зачем?

Комментариев нет:

Отправить комментарий