You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.


Step 1: Read the Image as Raw Binary Data

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.


Step 2: Write the Binary Data to Shared Memory

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);
}

Step 3: Read the Image from Shared Memory in Another Process

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());
}

Critical Tips to Avoid Headaches
  • Always Use Binary Mode: For both reading and writing files—skipping std::ios::binary on 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:40:50