2011-05-22 97 views
2

我想在2个进程中共享一个map的指针。所以我尝试了mmap。我在一个进程中测试了mmap。这里是我的代码:mmap后出现分割错误()

#include <vector> 
#include <iostream> 
#include <sys/mman.h> 
#include <unistd.h> 
#include <cstdlib> 
#include <stdio.h> 
#include <map> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    map<string,string> a, *b; 

    b = (map<string,string> *)mmap(&a,sizeof(map<string,string>), 
     PROT_READ|PROT_WRITE,MAP_ANON|MAP_SHARED,-1,0); 

    b->insert(map<string,string>::value_type("a","b")); //error 
    cout << b->size() << endl; 
} 
当它运行到 b->insert()

,分割故障发生。如果我删除b->insert(),则没有错误(仍然有b->size)。我的代码有什么问题?

+3

即使您将能够使用在mmap中分配的映射,它也不能在进程之间共享。 STL并不存储b中的所有元素,它使用通过new/delete或malloc/free工作的指针和经典分配器。如果你真的需要共享一些数据结构,你需要自己定义和实现它。 – osgx 2011-05-22 10:22:34

回答

1

您正在为mmap分配新的内存(为什么?似乎是一个坏主意......)但您并未初始化您的map。使用“放置新的”来初始化它。

void *p = mmap(....); 
if (p == MAP_FAILED) 
    abort(); 
map<string,string> *b = new(p) map<string,string>(); 
b->insert(...); 

但我怀疑的东西是可怕的错误,并mmap真的不应该在这里参与...

编辑:从评论,这听起来像你想分享两个进程之间的内存。共享内存可能远远超出您当前的技能水平。除非可以创建自定义分配器以仅在共享内存段内创建子对象,否则通常不会将对象放置在共享内存段中,因为它将包含对堆中内部对象的引用,除非您可以创建自定义分配器来创建子对象。

您可以使用shm_open创建共享内存对象,您可以使用ftruncate更改其大小,并且可以使用mmap将其映射到内存中。 shm_open同一名称的不同进程将获得相同的对象,并且共享对象描述符也可以在进程之间传递,就像文件描述符一样。

+0

我只是想在多个进程之间共享一个映射,有没有更好的方法? – Ace 2011-05-22 10:25:52

+0

@Alan:这不是'mmap'的工作方式。 – 2011-05-22 10:49:18

2

尽管它的名字,mmap()std::map无关。当你使用mmap()时,你可以访问一个没有结构的原始内存块。您不能直接在该块中存储类似std::map的STL对象,因为STL对象内部存在与mmap()不兼容的内部指针。

当您使用mmap()将同一块内存映射到两个不同的进程时,该块甚至可能不会出现在内存中的相同地址上。定义要存储在共享内存中的数据格式时,必须考虑到这一点。