用boost的Memory Mapped File如何规避alloc后当机造成的内存泄露?

Herro 2010-04-01 10:21:04
刚学boost的managed_mapped_file,用这个建立内存映射文件,然后创建了std兼容的allocator,传给map容器。让map容器用这个managed_mapped_file申请内存,这样2个进程的map可以完全同步。

但想到了一个问题,假设map在添加键值途中,它内部刚alloc了一个内存就停电或当机了,那么这片内存岂不是永远回收不了了?除非整个映射文件删除重新来,但架构不允许这么做。

这种问题要如何解决呢?

为了便于理解,示例大致代码:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

typedef managed_mapped_file::segment_manager segment_manager_t;
typedef allocator<void, segment_manager_t> void_allocator;

//让字符串也使用内存映射文件申请内存
typedef allocator<char, segment_manager_t> char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator> char_string;

//让map使用内存映射文件申请内存
typedef allocator<std::pair<const char_string, int>, segment_manager_t> map_value_type_allocator;
map< char_string, int, std::less<char_string>, map_value_type_allocator> string_map_type;


int main ()
{
//Create shared memory
managed_shared_memory segment(create_only,"MySharedMemory", 65536);

//An allocator convertible to any allocator<T, segment_manager_t> type
void_allocator alloc_inst (segment.get_segment_manager());

string_map_type *mymap = segment.construct<string_map_type>
//(object name), (first ctor parameter, second ctor parameter)
("MyMap")(std::less<char_string>(), alloc_inst);

char_string key_object("1234567890", alloc_inst);
//在这里停电
//key_object字符串实际上已经申请到映射文件中了,如果这里停电,这个内存将永远无法回收
mymap->insert(std::pair<const char_string, int>(key_object, 1));
//如果在insert途中停电,不知道map整个类会不会损坏或者其他问题。

}

还请有经验的人指导下。

...全文
514 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
yangyunzhao 2012-07-06
  • 打赏
  • 举报
回复
文件映射+定时同步就OK了
shendoulaixihuanwo 2011-11-10
  • 打赏
  • 举报
回复

char_string key_object("1234567890", alloc_inst);
//在这里停电
//key_object字符串实际上已经申请到映射文件中了,如果这里停电,这个内存将永远无法回收
mymap->insert(std::pair<const char_string, int>(key_object, 1));
插入方式不正确嘛
jackyjkchen 2010-04-02
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 herro 的回复:]
对,关键就是映射文件写到了磁盘里,我检查过了,开机读取这个文件那么这个区域的内存就泄露了。

to:icosagon
具体怎么说?又没相关讨论的地址,谢谢
[/Quote]
boost和ACE都是著名的通用C++库,相对来说boost偏向于更好的兼容linux而ACE则更好的兼容Windows。

从功能上说,Windows API涵盖面很广,而功能的全面性使得Windows API不需要什么技巧性的封装便可有足够的实用性(什么?API难用?说真的,我可不觉得过度设计的boost比api好用多少,问题的关键其实在于你更习惯C的方式还是C++的方式)。

浅层封装Windows/DirextX API,使其组织更有条理,便可胜任几乎一切工作,事实上这也是大量Windows Only的C++开发者的首选(主要体现在大型游戏的编写中)。

跨平台,说到底还是有代价的。
Herro 2010-04-02
  • 打赏
  • 举报
回复
对,关键就是映射文件写到了磁盘里,我检查过了,开机读取这个文件那么这个区域的内存就泄露了。

to:icosagon
具体怎么说?又没相关讨论的地址,谢谢
cattycat 2010-04-02
  • 打赏
  • 举报
回复
你开机的时候读内存区域肯定不存在啊,需要重新把文件映射进来。其实楼上说的很好,这种操作API的直接用windows的API没什么损失,一样很好操作。这些库封装的太臃肿了。
  • 打赏
  • 举报
回复
设置一个标志区域,标志区域可以在同一个文件内,也可以在不同文件中,写的时候先写这个标志区域,估计也就微秒级的时间,如果连这个都碰到了,那也没话可说了。
dengsf 2010-04-02
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 herro 的回复:]
就是说,你对内存alloc,windows会立即写入到文件,假设这时候停电没有释放内存,那么下次重新映射这个文件后,程序并不知道这片内存区域没有释放,而windows却认为这片内存区域已用,也就是说,这个映射文件中的内存泄露了。
[/Quote]
对系统来说,文件就是文件,
文件映射也只是运行时行为,重启后不再有什么内存映射的行为了。
难道是boost会在文件中记录分配信息?
如果是这样,断电后的信息维护一般不是程序的任务,而应采用UPS电源等其它手段避免;否则系统会很复杂。
Herro 2010-04-02
  • 打赏
  • 举报
回复
难道我没表达对意思= =
其实这个问题就算直接使用windows api也存在,boost只是我用的库。

就是说,你对内存alloc,windows会立即写入到文件,假设这时候停电没有释放内存,那么下次重新映射这个文件后,程序并不知道这片内存区域没有释放,而windows却认为这片内存区域已用,也就是说,这个映射文件中的内存泄露了。

假设这个映射文件需要长期为多个程序服务,那么这种情况是不可接受的。
icosagon 2010-04-01
  • 打赏
  • 举报
回复
这个库在windows上的稳定性不够牢固,特别是长时间运行的程序。
cattycat 2010-04-01
  • 打赏
  • 举报
回复
停电了或当机内存肯定不用清除了,关键是内存映射文件是不是写到磁盘文件中,估计可以开机文件检查时恢复的。

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧