boost interprocess vector不会释放共享内存

时间:2016-12-29 18:27:37

标签: c++ boost shared-memory

我使用boost :: interprocess在linux上的进程之间共享复杂的数据结构。它主要起作用,但是我的共享内存在每次更新共享数据时都会慢慢泄漏。

经过一些调试后,我能够提出相对较短的方法来重现这种行为:

#include <iostream>

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>


using UniversalAllocator = boost::interprocess::allocator
    < void
    , boost::interprocess::managed_shared_memory::segment_manager >;

using CharAllocator = boost::interprocess::allocator
    < char
    , boost::interprocess::managed_shared_memory::segment_manager >;

using ShmString = boost::interprocess::basic_string<char,   std::char_traits<char>, CharAllocator>;

struct Struct1
{
    Struct1(UniversalAllocator allocator)
        : member(allocator)
    {}
    struct Struct2
    {
        Struct2(UniversalAllocator allocator)
            : vector_member(allocator)
        {}
        struct Struct3
        {
            Struct3(UniversalAllocator allocator)
                : first(allocator)
                , second(allocator)
            {}
            ShmString first;
            ShmString second;
        };

        using Struct3Allocator = boost::interprocess::allocator
            < Struct3, boost::interprocess::managed_shared_memory::segment_manager >;
        using Structs3 = boost::interprocess::vector<Struct3, Struct3Allocator>;

        Structs3 vector_member;

    } member;
};

using Struct1Allocator = boost::interprocess::allocator
    < Struct1, boost::interprocess::managed_shared_memory::segment_manager >;

using Struct1Vector = boost::interprocess::vector
    < Struct1, Struct1Allocator>;


int main(void)
{
      boost::interprocess::managed_shared_memory segment(
          boost::interprocess::create_only,
          "TEST_MEMORY_LEAK",
          1500);
      std::cout << segment.get_free_memory() << std::endl;
      while(1)
      {
          Struct1Vector svector(segment.get_segment_manager());
          Struct1 selement(segment.get_segment_manager());
          svector.push_back(selement);
          std::cout << segment.get_free_memory() << std::endl;
      }
      return 0;
}

内存在push_back调用内部分配,但在离开范围时仅部分解除分配。结果:

$ g++ --std=c++11 -Wall -pthread -c memory_leak.cpp -o memory_leak.o
$ g++ memory_leak.o -o memory_leak -pthread -lrt
$ ./memory_leak
1276
1180
1132
1084
1036
988
940
892
844
796
748
700
652
604
556
508
460
412
364
316
268
220
172
124
76
28
terminate called after throwing an instance of 'boost::interprocess::bad_alloc'
  what():  boost::interprocess::bad_alloc
Aborted

奇怪的是,如果我将共享内存大小替换为1000(而不是1500),那么这个循环真的是无穷无尽的(最终会无限次地打印24次,所以内存泄漏到最后一刻然后......停止? )。

我正在使用boost 1.54和gcc 4.8.4如果重要的话,任何帮助都会非常感激,我有点想法:(

2 个答案:

答案 0 :(得分:0)

共享内存不像堆,但它不是你的堆。共享意味着锁定和锁定是昂贵的。您会注意到,managed_buffer / managed_mapped_file / managed_shared_memory段管理器将尽可能晚地回收内存(仅在分配失败时才可能)。

如果此时空闲内存开销太小,可能没有足够的空间来满足连续分配(因此您将优先考虑分配失败,作为泄漏的证据。实际上它是碎片的证据)。

答案 1 :(得分:0)

我继续实施我自己的内存管理算法(作为rbtree_best_fit上的一个瘦包装器,它是默认的,因此在上面的示例中使用)。我最终看到上面的代码在push_back上分配了两个段 - 一个非零长度和一个零长度,只解除前一个。这对我来说似乎不对,所以我搜索了推特网站的解释,发现我认为是issue。将系统升级升级到1.55后,上面打印1228次无限次(大概是正确的行为)。

相关问题