2016-12-29 75 views
1

我正在使用boost :: interprocess在Linux上的进程间共享复杂的数据结构。它主要工作,但我的共享内存缓慢泄漏每个共享数据的更新。boost进程间向量不会释放共享内存

一些调试后,我能够拿出比较短的方式来重现此问题:

#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 

奇怪足够多,若设为i替换共享存储器尺寸1000(而不是1500)的周期是忠实地无穷(它最终将印刷的次数24无限数目,所以内存泄漏到最后然后......停下来)。

我使用升压1.54和gcc 4.8.4如果它很重要,任何帮助将不胜感激,我有点运行的想法:(

回答

0

我继续并实现了自己的内存管理算法(作为rbtree_best_fit的一个薄包装器,这是默认的,因此在上面的示例中使用)。我最终看到上面的代码在push_back上分配了两个段 - 非零长度和零长度之一,并且仅释放前一个段。这似乎并不适合我,所以我搜索提升网站的解释,并发现我相信是issue。升级系统升级到1.55以上版本后,打印1228无限次(推测正确的行为)。

0

共享内存并不像堆,但它不是你的堆。共享意味着锁定和锁定代价很高,你会注意到managed_buffer/managed_mapped_file/managed_shared_memory分段管理器会尽可能晚地回收内存(只有当分配失败时才可能)

如果空闲内存开销太大在这种情况下,可能没有足够的空间来满足连续的分配(所以你会先分配失败,作为泄漏的证据。事实上,它是碎片证明)。

+0

好的,这是有道理的,虽然我不知道这是这里的问题(请参阅我的答案)。可悲的是,它似乎并没有完全解决我在真实项目中的问题,尽管目前还很难说(我必须用新的提升来重建很多依赖关系)。也许你对一个问题的看法也是对的,我应该在一段时间内调用shrink_to_fit或其他东西:) –

相关问题