使用mmap()映射空文件或程序内创建的文件时触发Bus error问题排查与解决
Hey there! Let's break down why you're seeing that "Bus error (core dumped)" message and get your code working as intended.
The Root Cause
When you create a new file with O_CREAT, its initial size is 0 bytes. When you use mmap() with MAP_SHARED to map this file, the kernel doesn't automatically expand the file to match your requested mapping size. Writing to memory addresses beyond the file's actual size triggers a bus error—there's no corresponding disk space allocated to back those addresses.
Step-by-Step Fixes
Here's what you need to adjust in your code:
Expand the file to your target size before mapping
Useftruncate()to set the file size toCOLUMN * ROWbytes. This tells the filesystem to allocate the necessary disk space for your mapped region.Add proper error checking
You missed checking the return values ofopen()andmmap()—these are critical for catching issues like failed file creation or mapping errors.
Modified Working Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <sys/stat.h> #define COLUMN 80 #define ROW 50 int32_t main(int32_t argc, char *argv[]) { struct stat sb; unsigned char *ptr; int32_t i; int32_t ret; int32_t fd; // Open or create the file with read/write permissions fd = open("my_test", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { perror("File Open Error"); return EXIT_FAILURE; // Exit immediately on open failure } // Expand the file to the required size before mapping ret = ftruncate(fd, COLUMN * ROW); if (ret == -1) { perror("ftruncate failed"); close(fd); return EXIT_FAILURE; } // Map the file into memory ptr = mmap(NULL, COLUMN * ROW, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { // Check if mmap succeeded perror("mmap failed"); close(fd); return EXIT_FAILURE; } // Write content to the mapped memory (syncs to file automatically with MAP_SHARED) for (i = 0 ; i < ROW ; i++) { // Ensure we don't exceed the column limit to avoid buffer overflow snprintf((char*)&ptr[i * COLUMN], COLUMN, "Line %d : \n", i); } // Unmap the memory ret = munmap(ptr, COLUMN * ROW); if (ret != 0) { perror("UnMapping Failed"); close(fd); return EXIT_FAILURE; } close(fd); return EXIT_SUCCESS; }
Key Notes
MAP_SHAREDBehavior: Any changes you make to theptrmemory region are automatically synchronized to the underlying file. This means external programs can open "my_test" and see the changes immediately (as long as the data has been flushed—though withMAP_SHARED, the kernel handles this automatically in most cases).- Buffer Safety: I replaced
sprintf()withsnprintf()to prevent writing beyond theCOLUMNlimit, which avoids buffer overflow issues. - File Permissions: The file is created with user read/write permissions—adjust the mode flags (
S_IRUSR | S_IWUSR) if you need to allow other users to access it.
内容的提问来源于stack exchange,提问作者Cprogrammer

