C++实现从磁盘读取文件写入共享内存以支持跨进程访问
Alright, since you’ve already got a working shared memory setup for strings via MSDN’s tutorials, let’s tweak that to handle image files properly. The main gotchas here are reading binary data correctly and making sure the shared memory setup accounts for raw byte streams instead of null-terminated strings.
First, forget using ostringstream for binary files—it’s designed for text and can mangle your image data. Instead, read the file directly into a byte buffer (we’ll use std::vector<char> for safe, managed memory):
#include <fstream> #include <vector> #include <stdexcept> std::vector<char> load_image(const std::string& img_path) { // Open file in binary mode and jump to the end to get size std::ifstream img_file(img_path, std::ios::binary | std::ios::ate); if (!img_file.is_open()) { throw std::runtime_error("Couldn't open image file: " + img_path); } // Get file size and jump back to start std::streamsize file_size = img_file.tellg(); img_file.seekg(0, std::ios::beg); // Allocate buffer and read the entire file std::vector<char> img_buffer(file_size); if (!img_file.read(img_buffer.data(), file_size)) { throw std::runtime_error("Failed to read image data from: " + img_path); } return img_buffer; }
This ensures you get every byte of the image exactly as it’s stored on disk—no text-mode transformations that would break PNG/JPEG structure.
Assuming your existing shared memory code uses Windows APIs (since you referenced MSDN), we’ll adjust it to store both the image size and the raw data. This lets the reading process know exactly how many bytes to pull:
#include <windows.h> void write_to_shared_memory(const std::vector<char>& img_data) { // Calculate total shared memory size: size marker + image data const size_t total_size = sizeof(size_t) + img_data.size(); // Create the shared memory file mapping HANDLE h_map = CreateFileMapping( INVALID_HANDLE_VALUE, // Use system page file NULL, // Default security attributes PAGE_READWRITE, // Allow read/write access 0, // High-order size (0 for <4GB) total_size, // Total size of shared memory L"ImageSharedMem"); // Unique name for the shared memory if (h_map == NULL) { throw std::runtime_error("CreateFileMapping failed. Error code: " + std::to_string(GetLastError())); } // Map the shared memory into the current process's address space LPVOID p_mem = MapViewOfFile( h_map, FILE_MAP_ALL_ACCESS, // Full read/write access 0, 0, 0); // Map entire region if (p_mem == NULL) { CloseHandle(h_map); throw std::runtime_error("MapViewOfFile failed. Error code: " + std::to_string(GetLastError())); } // First write the size of the image data, then the data itself size_t data_size = img_data.size(); memcpy(p_mem, &data_size, sizeof(size_t)); memcpy(static_cast<char*>(p_mem) + sizeof(size_t), img_data.data(), data_size); // Note: Don't unmap/close the handles here if you want other processes to access the memory // UnmapViewOfFile(p_mem); // CloseHandle(h_map); }
The reading process needs to first grab the size marker, then read the corresponding number of bytes:
#include <windows.h> #include <vector> std::vector<char> read_from_shared_memory() { // Open the existing shared memory object HANDLE h_map = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, // Don't inherit handle L"ImageSharedMem"); // Same unique name as writer if (h_map == NULL) { throw std::runtime_error("OpenFileMapping failed. Error code: " + std::to_string(GetLastError())); } // Map the memory into this process's address space LPVOID p_mem = MapViewOfFile( h_map, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (p_mem == NULL) { CloseHandle(h_map); throw std::runtime_error("MapViewOfFile failed. Error code: " + std::to_string(GetLastError())); } // Read the size marker first size_t data_size = *static_cast<size_t*>(p_mem); // Allocate buffer and read the image data std::vector<char> img_buffer(data_size); memcpy(img_buffer.data(), static_cast<char*>(p_mem) + sizeof(size_t), data_size); // Clean up resources UnmapViewOfFile(p_mem); CloseHandle(h_map); return img_buffer; }
To verify it works, you can write the buffer back to a file:
void save_image(const std::vector<char>& img_buffer, const std::string& output_path) { std::ofstream out_file(output_path, std::ios::binary); if (!out_file.is_open()) { throw std::runtime_error("Couldn't open output file: " + output_path); } out_file.write(img_buffer.data(), img_buffer.size()); }
- Always Use Binary Mode: For both reading and writing files—skipping
std::ios::binaryon Windows will corrupt your image by converting line endings. - Synchronize Access: If multiple processes are interacting with the shared memory, use a mutex or event to prevent race conditions (e.g., signal the reader when the writer finishes writing).
- Clean Up Resources: Make sure to unmap the view and close handles when you’re done with the shared memory to avoid leaks.
- Unique Shared Memory Names: Use a unique name (like
L"YourAppName_ImageSharedMem") to avoid conflicts with other applications.
内容的提问来源于stack exchange,提问作者Jdv

