#c #c 11 #c 14
#c #c 11 #c 14
Вопрос:
Как мы можем отменить выделение памяти, выделенной в статической функции-члене, используя std::memory_resource::allocate()
?
Я попытался использовать функцию deleter, передающую unique_ptr
вместо default_delete
. В этом случае это освобождает память распределителя.
Проблемы заключаются в:
- Я не уверен в продолжительности жизни объекта распределителя до конца
unique_ptr
выхода из области видимости - Я не хочу изменять сигнатуру статической функции ниже формы, используя метод удаления.
например:
static std::unique_ptr<base,std::functional<void(base*)>> create(std::pmr::memory_resource* all)
{
void* ptr = all->allocate(sizeof(base));
std::unique_ptr<base, std::function<void(base*)> up(new base(), [amp;all]
(base* b){ all->deallocate(b,sizeof(base));
return std::move(up);
}
// Фактический исходный код
#define _CRTDBG_MAP_ALLOC
#include <iostream>
#include <memory_resource>
#include <memory>
#include <functional>
using namespace std;
class base
{
int val = 0;
public:
base()
{
}
~base()
{
cout << "dest" << endl;
}
static std::unique_ptr<base> create(std::pmr::memory_resource* all)
{
void* ptr = all->allocate(sizeof(base));
return std::unique_ptr<base>(new(ptr) base());
}
};
int main()
{
{
{
std::pmr::memory_resource* all = std::pmr::get_default_resource();
auto b1 = base::create(all);
auto b2 = base::create(all);
}
_CrtDumpMemoryLeaks();
}
return 0;
}
Я хочу освободить память, выделенную в статическом методе, без изменения сигнатуры функции (означает добавление функции удаления в unique_ptr
).
Предложите любое решение для решения этой проблемы, и, пожалуйста, также укажите различные способы освобождения памяти, выделенной в этом примере кода с помощью allocate()
.
Ответ №1:
Память, выделенная с std::pmr::memory_resource::allocate
помощью, должна быть освобождена с помощью std::pmr::memory_resource::deallocate
.
Поэтому делать следующее неправильно:
void* ptr = all->allocate(sizeof(base));
return std::unique_ptr<base>(new(ptr) base());
Проблема здесь в том, что unique_ptr
будет вызываться delete
указатель, удерживаемый ptr
, и это недопустимо. С этого момента вы должны предоставить пользовательский параметр удаления, обойти это невозможно.
Поскольку неясно, какую проблему вы хотите решить memory_resource::allocate
, на самом деле невозможно сказать, как вы могли бы ее решить. Выделение памяти для каждого объекта кажется, по крайней мере, очень странным и указывает на то, что ваш подход неверен.
Комментарии:
1. void* ptr = all->allocate(sizeof(base)); возвращает std::unique_ptr<base>(new(ptr) base()); почему этот код неправильный? не могли бы вы подробнее объяснить это. Насколько я понимаю, unique_ptr вызовет базовый деструктор, когда он выйдет из области видимости. Мое требование заключается в том, что я должен создать базовый объект внутри статической функции, используя объект распределителя. Объект распределителя будет передан в качестве входного аргумента статической функции. Когда мой unique_ptr выходит за рамки, он должен автоматически освободить память.
2. @Mahendra Как я уже сказал, поведение a по умолчанию
unique_ptr
заключается в том, что он будет вызыватьdelete
указатель, которым он управляет, и это допустимо только в том случае, если этот указатель был выделен с использованиемnew
. Если вы это сделаетеbase * b = new(ptr) base()
, то вам не разрешено делатьdelete b
, вам разрешено только вызывать деструктор на немb->~base();
.3. Я попытался сохранить объект указателя распределителя и объект ptr внутри vector. когда unique_ptr выходит из области видимости, он вызывает деструктор base() . Внутри базового деструктора я освобождаю память, используя объект распределителя, хранящийся внутри vector, и присваиваю ptr-объекту значение null. Но проблема в том, что unique_ptr вызывает исключение после выполнения базового деструктора(). Из этого я понял, что unique_ptr пытается освободить память.например: вектор<std::tuple<база *amp;,Распределитель *>> контейнер для хранения распределителя и базы * .
4. @Mahendra в вашем опубликованном коде вы делаете
std::unique_ptr up(new base(), [amp;all](base* b){ all->deallocate(b,sizeof(base));
это в своем примере, который вы вызываете,all->deallocate
по указателю, который создается не сall->allocate
помощью , а сnew base()
помощью .