写入内存映射文件时触发Bus Error问题求助
Bus Error 问题分析与修复
问题根源
你的代码中db_file_open函数使用fopen(path, "w+")打开文件,这个模式会强制截断已存在的文件至0长度。之前在disk_io_create_disk_file中通过ftruncate设置的文件大小会被清空,导致db_file_init_hdr中mmap的区域实际上超出了文件的实际大小,写入操作触发Bus Error。
另外还有两处潜在问题:
mmap失败时返回的是MAP_FAILED(值为(void*)-1),而非NULL,原代码的assert(pptr)无法正确检测mmap失败。- 代码中未给出
disk_file_unmap的实现,需要补充调用munmap的逻辑。
修复方案
- 修改
db_file_open的文件打开模式为"r+",打开已存在文件时不截断:
fd_t db_file_open (const char* path) { FILE *file = fopen (path, "r+"); if (!file) assert(0); fd_t fd = fileno (file); return fd; }
- 完善
disk_io_file_mmap的错误检测:
void * disk_io_file_mmap (fd_t fd, uint64_t start_offset, uint64_t end_offset) { size_t map_size = end_offset - start_offset; void *pptr = mmap (NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start_offset); // mmap失败返回MAP_FAILED,需正确检测 assert(pptr != MAP_FAILED); return pptr; }
- 补充
disk_file_unmap的实现:
void disk_file_unmap(void *addr, size_t size) { assert(munmap(addr, size) != -1); }
关键说明
"w+"模式会清空已有文件内容并重置长度,这是导致映射区域无效的核心原因;"r+"模式用于读写已存在的文件,不会修改文件长度。- mmap的映射区域必须对应文件的实际有效范围,当文件长度被截断后,原映射的区域超出文件实际大小,写入时会触发Bus Error或Segmentation Fault。
内容的提问来源于stack exchange,提问作者Abhishek Sagar
相关产品推荐
相关产品推荐

