【问题标题】:Bus error with mmap memory regionmmap 内存区域的总线错误
【发布时间】:2018-06-29 04:17:06
【问题描述】:

在下面的简单程序中:

# include <sys/mman.h>
# include <fcntl.h>
# include <cstdlib>

# include <cassert>

struct rgn_desc
{
  size_t end_;
  char data[];
};

int main(int argc, const char *argv[])
{
  int fd = open("foo.mm", O_RDWR|O_CREAT|O_TRUNC, (mode_t)0700);

  assert(fd != -1);

  void * ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
                    MAP_SHARED | MAP_POPULATE, fd, 0);

  assert(ptr != (void*) -1);

  rgn_desc * rgn_ptr = (rgn_desc*) ptr;
  rgn_ptr->end_ = 0; // <-- bus error
}

基本上,我想管理一个简单的 mmaped arena 分配器,并将我分配的字节存储为映射的第一部分。因此,当我从文件中恢复时,我会知道分配了多少字节。

但是,最后一行给了我一个bus error。有人可以解释为什么,如果可能的话,向我建议一种避免它的方法。我在 32 位奔腾上运行 Linux 并使用 clang++ 编译器

【问题讨论】:

  • assert 语句替换为if (ptr == MAP_FAILED) perror("mmap"), exit(EXIT_FAILURE);,然后使用调试器和strace
  • 我提出了@Basile 建议 (if (ptr == MAP_FAILED...) 并删除了 MAP_POPULATE。我仍然得到错误。
  • 你也使用strace吗?
  • @Stargateur:这应该是答案。
  • 这适用于ftruncate(fd, 4096);。请公布答案,我很乐意投票并接受。

标签: c++ mmap


【解决方案1】:

根据文档,在以下情况下可以触发 sig 总线:

SIGBUS
    Attempted access to a portion of the buffer that does not
    correspond to the file (for example, beyond the end of the
    file, including the case where another process has truncated
    the file).

在您的剪辑中,您的文件大小与您的 mmap() 大小(0、4096)不匹配,因此您可以使用 ftruncate() 来增加文件的大小。

ftruncate(fd, 4096);

【讨论】:

  • 非常感谢。只有一件事:我不确定您对MAP_POPULATE 的引用是否将其用于非私有映射。我的理解是,支持是从 2.6.23 开始而不是之前,但这并不意味着,正如我所解释的那样,与其他标志一起使用是被禁止的。
猜你喜欢
  • 2020-09-20
  • 2017-10-30
  • 1970-01-01
  • 2023-03-30
  • 2014-05-20
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多