очистка boost :: pool_allocator для std :: map не возвращает весь пул в VS2017 - PullRequest
0 голосов
/ 25 мая 2018

Когда я запускаю следующий код в VS2017:

#include <boost/pool/pool_alloc.hpp>
#include <map>
#include <iostream>

int main()
{
    using Map = std::map<int, int, std::less<int>, boost::pool_allocator<std::pair<const int, int>>>;
    using Pool = boost::singleton_pool<boost::pool_allocator_tag, sizeof(Map)>;

    Map temp;

    for (int i = 1; i < 5; i++) temp[i] = i;

    std::cout << "First addresses:\n";
    for (auto& kv : temp) std::cout << &kv.second << "\n";

    temp.clear();
    Pool::purge_memory();

    Map temp2;

    for (int i = 1; i < 5; i++) temp2[i] = i;

    std::cout << "Second addresses:\n";
    for (auto& kv : temp2) std::cout << &kv.second << "\n";

    temp2.clear();
    Pool::purge_memory();

    return 0;
}

, я получаю вывод:

First addresses:
02A108F4
02A1090C
02A10924
02A1093C
Second addresses:
02A1090C
02A10924
02A1093C
02A10954

Живой пример

Этоповедение кажется неправильным: что случилось с адресом 02A108F4?Кажется, он не был возвращен в пул во время очистки.

Этого не происходит, когда я использую std::vector вместо std::map.Кажется, что gcc также правильно возвращает память: Живой пример .

Это ошибка в VS2017?

1 Ответ

0 голосов
/ 25 мая 2018

Вы предполагаете что-то о деталях реализации пула.Вполне возможно, вы правы, что есть потеря, но вы не можете сделать это из шаблонов распределения, которые вы видите.

Кроме того, вы очищаете память для распределителя пула, связанного с sizeof(int).Однако value_type уже равен std::pair<int const, int>, и это оставляет тот факт, что реализация карты вместо этого выделяет неопределенный тип узла.

Oh, и причина, по которой ваш распределитель работал, точно такая же:Реализация контейнера знает , что вы не можете предоставить правильный тип распределителя, поскольку выделенный тип не определен.Поэтому он всегда будет перепривязывать , чтобы получить требуемый тип .

Так что, по крайней мере, сделайте это

Live On Rextester

#include <boost/pool/pool_alloc.hpp>
#include <map>
#include <iostream>

using Map = std::map<int, int, std::less<int>, boost::pool_allocator<int>>;
using Pool = boost::singleton_pool<boost::pool_allocator_tag, sizeof(Map::value_type)>;

void foo() {
    Map temp;

    for (int i = 1; i < 5; i++) temp[i] = i;

    std::cout << "First addresses:\n";
    for (auto& kv : temp) std::cout << &kv.second << "\n";
}

int main()
{
    foo();
    Pool::purge_memory();

    foo();
    Pool::purge_memory();
}

Это, хотя все еще предполагает детали реализации.Я думаю, c ++ 17 дает вам больше информации для работы с (http://en.cppreference.com/w/cpp/container/node_handle), иначе вы могли бы увидеть, что Whest Boost Container имеет соответствующие данные: https://www.boost.org/doc/libs/1_51_0/doc/html/boost/container/map.html#id463544-bb

...