将strcpy用于mmap的文件时出现总线错误(核心转储)

时间:2015-10-29 16:18:47

标签: c strcpy

我有一个简单的程序:

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。但根据定义,我认为没有问题。

1 个答案:

答案 0 :(得分:5)

如果

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信号的传递。

类似地,Linux上的man mmap注释

  

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

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