【问题标题】:purging the boost::pool_allocator for a std::map does not return the whole pool in VS2017清除 std::map 的 boost::pool_allocator 不会返回 VS2017 中的整个池
【发布时间】:2018-11-04 20:28:27
【问题描述】:

当我在 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

Live example

这种行为似乎不正确:地址02A108F4 发生了什么?在清除过程中它似乎没有返回到池中。

当我使用 std::vector 而不是 std::map 时,不会发生这种情况。 gcc 似乎也能正确返回内存:Live example

这是 VS2017 中的错误吗?

【问题讨论】:

  • 在您添加的实时示例中,该行为不会发生。
  • 是的,我就是这么说的:在 GCC 中,活生生的例子,它有效。在 VC++ 中它没有。我将添加一个VC++的实例
  • 现场示例 MSVC:rextester.com/BWANL51397
  • 我写了所有这些作为答案:)

标签: c++ visual-studio boost pool stdmap


【解决方案1】:

您假设有关池的实施细节。你可能是对的,有损失,但你不能从你看到的分配模式中得出结论。

此外,您正在清除与sizeof(int) 关联的池分配器的内存。然而,value_type 已经是std::pair&lt;int const, int&gt;,这就留下了 map 实现分配一个未指定的节点类型的事实。

哦,你的分配器工作的原因完全相同:容器实现知道你不可能提供正确的分配器类型,因为分配的类型是未指定的。因此它总是rebind to get the required type

所以,至少做到了

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),否则您可以查看 Boost Container 是否有相关详细信息:https://www.boost.org/doc/libs/1_51_0/doc/html/boost/container/map.html#id463544-bb

【讨论】:

  • 我刚刚在答案中添加了一个注释。我们一直是我们的尾巴:)
  • 啊,但现在在我的示例中,我有两张地图 temptemp2 ,同样的问题再次出现。即使您进行了修改。 Live example。我没用delete,我用purge,所以应该把所有内存都还回来吧?
  • 我认为std::map 在创建对象时使用分配器存储了额外的东西。但这似乎只发生在 VC++ 中而不是 GCC 中。
  • @JHBonarius 在这种情况下,我看不到 std::map 在侧面进行少量分配的问题。如果是rextester.com/IFF93902 ?
  • 我在不破坏map时遇到了一些额外的信息,来自“马口”解释clear()之后挥之不去的分配:twitter.com/CoderCasey/status/1005578618578325506(请务必阅读整个线程)
猜你喜欢
  • 2019-08-17
  • 1970-01-01
  • 1970-01-01
  • 2013-09-20
  • 1970-01-01
  • 1970-01-01
  • 2014-11-29
  • 2013-07-14
  • 1970-01-01
相关资源
最近更新 更多