2016-12-29 77 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或其他東西:) –

相關問題