mmap共享内存中的字符串c ++

时间:2014-03-20 10:52:01

标签: c++ segmentation-fault fork shared-memory mmap

我的程序有段错误。

我正在尝试从forks访问字符串,但我甚至无法将数据放到共享内存中。

我的代码:

static string * currentSessionIP;

int main(int argc, char *argv[])
{
    currentSessionIP = static_cast<string*>(mmap(NULL, 4096, PROT_READ | PROT_WRITE,
         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
    *currentSessionIP = "";
}

mmap时没有错误,但是当我尝试分配某些东西时,它就是段错误。

如何从任何fork()访问字符串,甚至更改它? 提前谢谢!

3 个答案:

答案 0 :(得分:2)

你没有构建std::string,即称之为构造函数。构造函数负责初始化对象数据。想象string就像这样实现:

struct string {
    char* data;
    size_t length;
    // ...
};

您使用强制转换将此结构放在有效内存中,没有问题,但字段datalength的值未初始化,因此data指向随机地址并且length是垃圾,因此当你使用字符串时会发生崩溃。在使用之前,您必须显式调用构造函数,例如currentSessionIP->string();,但在C++中这是不可能的。相反,你必须使用placement new语法,它将强制转换和对构造函数的调用结合起来,如下所示:

void * mem = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));

currentSessionIP = new (mem) string;

由于您确定调用构造函数,因此此语法更短更安全。但是你还没有完成,因为string结构将在共享内存中,但那只是&#34;标题&#34; :data没有理由指向共享内存块。

默认情况下,std::string使用std::allocator在程序堆上使用标准内存分配。解决方案是使用自定义分配器(std::basic_string的模板参数)来确保data始终指向共享内存。在初始化和调整字符串大小时,字符串对象将调用您的分配器。

看看at this tutorialboost interprocess,同时下面是一个非常粗略和不完整的实现,只是为了深入了解一个想法:

// a very simple shared memory allocator
struct shared_alloc {
    typedef char value_type;
    typedef char* pointer;
    //... see http://en.cppreference.com/w/cpp/memory/allocator

    pointer cur; // points to a free memory location
    shared_alloc() {
        cur = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
        // todo: lifecycle (free memory block sometime)
    }
    pointer allocate(size_t n) {
        pointer p = cur;
        cur += n; // todo bound checking
        return p;
    }
    void deallocate(pointer p, size_t n) {
        // todo: do something smart
    }
};

// an allocator object
shared_alloc alloc;

// a string with a custom allocator
typedef std::basic_string<char, std::char_traits<char>, shared_alloc> shared_string;

// allocate shared mem for the string object (the header)
void * header_mem = alloc.allocate(sizeof(shared_string));

// create a string object at this location, and use our allocator for the data
shared_string * currentSessionIP =
  new( header_mem ) shared_string(alloc);

答案 1 :(得分:0)

std::string是一个对象,而不仅仅是一个连续的内存缓冲区。您必须初始化字符串,或者使用placement new运算符来创建字符串对象。

答案 2 :(得分:0)

您对mmap的调用会返回指向未初始化内存的指针。它没有指向字符串。仅仅因为你将指针投向string*并不会在std::string指向的位置神奇地创建currentSessionIP

执行*currentSessionIP = ""时,您尝试修改的内容并非std::string,因此会出现段错误。

如果你真的想要,你可以使用placement new在该位置创建一个字符串,但我不建议这样做。