使用mmap时的segfault
segfault when using mmap
我第一次尝试使用mmap来存储一个包含大量数据的树对象。树类基本上包含一个指向类Node根的指针,每个Node实例都有一个指向其子对象的指针数组。我认为mmap正在做它应该做的事情,因为我可以访问树的常量成员,但当我试图访问指向根的指针时,我会得到一个segfault。
以下是如何创建具有根节点的树:
int main(int argc, char *argv[])
{
Tree *map;
...
map = (Tree*)mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
close(fd);
perror("Error mmapping the file");
exit(EXIT_FAILURE);
}
Node* root = new Node("data");
map->set_root(root);
...
}
以下是我访问树的方式:
int main(int argc, char *argv[])
{
int i;
int fd;
Tree *map;
fd = open(FILEPATH, O_RDONLY);
if (fd == -1) {
perror("Error opening file for reading");
exit(EXIT_FAILURE);
}
map = (Tree*)mmap(0, FILESIZE, PROT_READ, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
close(fd);
perror("Error mmapping the file");
exit(EXIT_FAILURE);
}
Node* root = map->root();
cout << root->data();
...
root->data((的输出提供了一个segfault。有人能告诉我哪里错了吗?如果我没有把问题说清楚,请说出来。
提前谢谢。
Mads
这一团糟。在尝试你要做的事情之前,你需要了解new
和delete
是如何工作的
从哪里开始。
map = (Tree*)mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
这只是说,把这段内存当作Tree
来处理,你还没有在这段内存中构建一棵树- 当您调用
new
时,它会在内存中的某个位置分配一个Node
对象,并且您在树中持有指向该对象的指针,当它在其他位置重新打开时,该指针将不再有效
您还需要将所有节点存储在映射块中。。。除了尝试理解自定义内存分配器之外,没有真正简单的答案。
当您调用mmap()
时,您基本上只得到一块原始内存。因此,如果不调用某种类型的未定义行为,就不能天真地取消引用指针map
。。。像您所做的那样简单地将从mmap()
返回的内存强制转换为类型Tree*
实际上并不会在映射的内存中构造Tree
对象。
如果您希望在从mmap
返回的内存中构造甚至复制构造Tree
对象,您可能需要研究使用placement new
。例如,您可以执行以下操作:
void* map;
map = mmap(0, FILESIZE, PROT_READ, MAP_SHARED, fd, 0);
//...error checking
Tree* tree = new(map) Tree(); //placement new syntax
这实际上会在从mmap
返回的内存中默认构造一个Tree
对象,此时,您可以正确地使用tree
指针变量,以便进一步向树中添加节点。例如,现在可以在不创建未定义行为的情况下调用以下代码:
Node* root = new Node("data");
tree->set_root(root);
使用placement new
,变量tree
将指向一个实际的Tree
对象,现在您可以正确地取消引用该指针以及与该对象关联的任何方法。
不过,需要记住的一个主要事项是,当使用placement new
时,您必须手动调用Tree
对象的析构函数,并且必须手动释放通过mmap()
分配的内存。。。您不能在Tree*
上呼叫delete
。
这行不通。如果root()
是一个虚拟方法,则会被冲洗,因为vtable指针指向当前进程中的方法。如果您不调用任何虚拟方法,它可能会工作,但它可能是未定义的行为。
在进程之间共享数据可能比在对象之间共享数据更好。让对象拥有数据的句柄,并保护对象的用户不受解码数据细节的影响。Node* root = new Tree(memory_mapped_memory);
- 理解boost::asio-async_read在无需读取内容时的行为
- ostream过载时的缓冲区冲洗
- 具有未知值时的时间复杂性
- 编译时的 CImg 库返回对"__imp_SetDIBitsToDevice"的未定义引用
- 当比特(而不是字节)的顺序至关重要时的持久性
- 旋转模型矩阵时的形状失真
- 讨论 - 创建矩阵时的数组与向量的向量 - 什么是最实用的选择
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 打印第二列时的2d字符矢量打印空间
- 读取文件时运行时的未知行为
- posix_spawn():使用posix_scawn()时的错误处理问题
- 查找最近配对时的OpenMP竞赛条件
- 使用 gmock 时的 SegFault
- 使用std :: to_string()创建std :: String时的segfault
- 呼叫时的segfault,但不跳到rax中的地址
- 调用 glGenFramebuffers() 时的 Segfault
- 分类向量时的segfault
- 使用共享指针访问单例子类时的SEGFAULT
- 访问成员stl映射时的C++Segfault
- 使用mmap时的segfault