【问题标题】:Bus error (core dumped) when using strcpy to a mmap'ed file将 strcpy 用于 mmap 文件时出现总线错误(核心转储)
【发布时间】:2016-01-29 21:47:11
【问题描述】:

我有一个简单的程序:

int main(void) {
   int fd;
   const char *text = "This is a test";

   fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) );
   if ( fd < 0 ) {
           perror("open() error");
           return fd;
   }

    /* mmap the file. */
   void *address;
   off_t my_offset = 0;
   address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset);

   if ( address == MAP_FAILED ) {
           perror("mmap error. " );
           return -1;
   }

    /* Move some data into the file using memory map. */
    strcpy( (char *)address, text);

    /* use msync to write changes to disk. */
    if ( msync( address, 4096 , MS_SYNC ) < 0 ) {
    perror("msync failed with error:");
        return -1;
    }
    else {
    printf("%s","msync completed successfully.");
}

    close(fd);
    unlink("/tmp/msyncTest");
}

我的代码有什么问题吗?我做了一些简单的测试,似乎问题来自strcpy。但是按照定义,我觉得没有问题。

【问题讨论】:

  • 你还没有展示如何检查fd;如何设置lenmy_offset;你如何检查mmap() 电话。我们可以猜测与这些相关的某些东西导致代码失败。
  • @JonathanLeffler 好的,我会发布所有代码。
  • 我们只需要查看一个 MCVE (How to create a Minimal, Complete, and Verifiable Example?) — 可能还有 10 行左右。
  • 如果文件是新创建的(正如O_CREAT 暗示的那样),它将是零大小的。访问与基础文件(如果有)不对应的mmap()ed 区域的一部分会导致 sigbus。解决方法:ftruncate()mmap()之前的文件。
  • @EOF:您应该将其作为答案,以便 OP 可以接受。我点击这个问题来回答它,因为它没有答案,结果发现它已经有了答案,但是作为评论而不是答案提交。 :-p

标签: c strcpy


【解决方案1】:

如果

fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) );

成功,fd 将引用零长度文件 (O_TRUNC)。拨打mmap()

address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset);

建立了内存映射,但页面不对应对象。

http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html对这种情况有以下说法:

系统总是在对象末尾处零填充任何部分页面。此外,系统从不写出对象最后一页超出其末尾的任何修改部分。地址范围内的引用从 pa 开始并持续 len 字节到对象结束后的整个页面,从而导致 SIGBUS 信号的传递。

同样,man mmap 在 Linux 笔记中

使用映射区域可能会导致以下信号:
[...]
SIGBUS 尝试访问与文件不对应的缓冲区部分(例如例如,超出文件末尾,包括另一个进程截断文件的情况。

因此,您必须将文件ftruncate() 设置为非零长度之前 mmap()ing(除非您是mmap()ing 匿名内存)。

【讨论】:

  • 一个细节:ftruncate 不必出现在mmap 之前;它可以在mmap 之后完成,只要它发生在任何会出错的访问之前。
  • @R.. 我会强烈建议不要这样做:pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.htmlIf the size of the mapped file changes after the call to mmap() as a result of some other operation on the mapped file, the effect of references to portions of the mapped region that correspond to added or removed portions of the file is unspecified.Linux man mmap: The effect of changing the size of the underlying file of a mapping on the pages that correspond to added or removed regions of the file is unspecified.
猜你喜欢
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多