我的程序有段错误。
我正在尝试从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()访问字符串,甚至更改它? 提前谢谢!
答案 0 :(得分:2)
你没有构建std::string
,即称之为构造函数。构造函数负责初始化对象数据。想象string
就像这样实现:
struct string {
char* data;
size_t length;
// ...
};
您使用强制转换将此结构放在有效内存中,没有问题,但字段data
和length
的值未初始化,因此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 tutorial或boost 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在该位置创建一个字符串,但我不建议这样做。