Должен ли вызов malloc совпадать с вызовом free в пуле динамической памяти?

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

Вызов malloc НЕ совпадает с вызовом free. Похоже, что приложение, которое использует его, не вызывает достаточное количество новых последовательностей, чтобы приложение могло утечь значительный объем памяти.

Я не писал это, так что это мое лучшее предположение.

Мой вопрос:

  1. Является ли отсутствие вызова для освобождения ошибкой или я что-то упускаю из-за перегрузки оператора удаления?
  2. Полагается ли эта реализация на то, что ОС будет очищать небольшой объем памяти, который действительно просачивается при выходе?

Спасибо.

//Obj.h
class Obj
{
public:
    Obj(){};
    void* operator new(std::size_t size);
    void operator delete(void* p);
private:
    static std::vector<void*> pool_;
    static std::size_t checked_in_;
    static std::size_t checked_out_;
};

//Obj.cpp
std::vector<void*> Obj::pool_;
std::size_t Obj::checked_out_ = 0;
std::size_t Obj::checked_in_  = 0;

void* Obj::operator new(std::size_t size)
{
    if (pool_.empty())
    {
        ++checked_out_;
        return malloc(size);
    }
    else
    {
        --checked_in_;
        ++checked_out_;
        void* p = pool_.back();
        pool_.pop_back();
        return p;
    }
}

void Obj::operator delete(void* p)
{
    pool_.push_back(p);
    if (pool_.size() % 10000 == 0)
    {
        std::cout<<"mem leak\n";
    }
    --checked_out_;
    ++checked_in_;
}

person Carl    schedule 16.04.2013    source источник
comment
Если быть точным, он полагается на приложение, которое его использует, чтобы не резко сократить количество выделений, которые ему требуются из пула одновременно. Это довольно паршивая реализация, потому что было бы тривиально решить проблему с помощью незначительной корректировки кода. (Проверьте размер перед вызовом push_back. Если пул заполнен, вместо вызова push_back и увеличения checked_in вызовите free и не увеличивайте checked_in.) А ​​что делать с checked_in? -- это идеально дублирует pool_.size(). Зачем отслеживать одно и то же дважды?   -  person David Schwartz    schedule 16.04.2013
comment
Спасибо за это. Всегда приятно узнать, что это не неясный уголок стандарта C++, который сбивает вас с толку.   -  person Carl    schedule 16.04.2013


Ответы (2)


Отсутствующий «бесплатный» означает, что вы не можете встроить это в какое-то более крупное приложение, запустить его, закрыть и вернуться к тому, с чего начали. Это нормально, если вы управляете всем приложением, и не очень хорошо, если этот код фактически должен быть встраиваемым. Чтобы это сработало, вам понадобится некоторая точка входа, которая будет свободно проходить вызовы вектора.

Он никогда не протекает в общепринятом смысле, так как каждый блок памяти сохраняется в векторе оператором удаления для повторного использования, а оператор удаления жалуется, если видит слишком много элементов в векторе.

person bmargulies    schedule 16.04.2013
comment
Да, это было модульное тестирование некоторого устаревшего кода, который использовал это внутренне, что привело меня к обнаружению этой ошибки. - person Carl; 16.04.2013

Вы создаете пул памяти. Эта реализация пула будет расти по мере необходимости, но никогда не вернет память ОС. Обычно это ошибка, но не при создании собственного метода выделения памяти, пока этот пул существует на протяжении всей жизни вашей программы. У вас произойдет утечка при выходе из программы, но, скорее всего, вы сможете с этим смириться. По сути, вы переопределяете то, как обычно работает new/malloc, и полностью делаете память самостоятельно.

person Gabe Sechan    schedule 16.04.2013