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

C++跨进程指定地址读写数据失效问题技术求助

问题:进程间通过硬编码内存地址交换数据,修改后无法同步更新

你遇到的核心问题是每个Windows进程都拥有独立的虚拟地址空间,你硬编码的speed_address在两个进程中指向的是各自虚拟空间里的内存区域,并不是真正的共享物理内存。所以Program1修改的是自己进程内的内存,Program2读取的是自己进程内同虚拟地址的内存,两者完全不相干,自然看不到更新。

先看你提供的代码:

Program1.cpp

#include <iostream>
#include <windows.h>
#include "DataExchange.h"
using namespace std;
int main(int argc, char** argv) {
    double val2 = 0;
    double spd = 1;
    double* ptr2 = (double*)speed_address;
    cout << "Program1" << endl;
    while(1){
        DXSetvalue (Speed, spd);
        val2 = DXGetvalue (Speed);
        cout << "[speed] = " << spd++ << " [获取到的speed值] = " << val2 << " [地址] = " << ptr2 << "\r" ;
        Sleep(2000); // 2秒
    }
    return 0;
}

Program2.cpp

#include <iostream>
#include <windows.h>
#include "DataExchange.h"
using namespace std;
int main(int argc, char** argv) {
    double t = 0;
    double val = 0;
    int* ptr = (int*)speed_address;
    cout << "Program1 Node" <<endl;
    init();
    while(1){
        t += 2;
        val = DXGetvalue (Speed);
        cout << "(" << t << "秒) " <<"[Speed] = " << val << " [共享内存地址] = " << ptr << "\r";
        Sleep(2000);
    }
}

DataExchange.h

#include "stdio.h"
// 值ID宏定义
#define Speed 1
// 值的地址定义
//#define speed_address 0x4a8048
//#define speed_address 0x00CFFB3C
#define speed_address 0x7ffef8
// 函数声明
void setaddressValue (double* address, double d);
double getaddressValue (int name);
double* addressID (int name);
void DXSetvalue (int name, double d);
double DXGetvalue (int name);
void init();
// 函数定义
void setaddressValue (double* address, double d){
    double* p = (double*)address;
    *p = d;
    //printf("p = 0x%x *p = %lf\n", p, *p);
}
double getaddressValue (int name){
    double* pGet = addressID(name);
    double value = *pGet;
    //printf("pGet = 0x%x *pGet = %lf\n", pGet, *pGet);
    return value;
}
double* addressID (int name){
    switch (name){
        case 1:
            return (double*)speed_address;
        default:
            //cout << "未设置地址" << endl;
            printf("未设置地址!!!\n");
    }
}
/*程序数据*/
void DXSetvalue (int name, double d){
    setaddressValue(addressID(name), d);
}
double DXGetvalue (int name){
    return getaddressValue (name);
}
void init(){
    double* p = (double*)speed_address;
    *p = 0.5;
}

解决方案:使用Windows共享内存机制

要实现真正的进程间内存共享,必须使用Windows提供的CreateFileMapping和MapViewOfFileAPI,它们会创建一块所有进程都能访问的共享物理内存区域。

下面是修改后的代码实现:

新的DataExchange.h

#include <windows.h>
#include <stdio.h>

// 值ID宏定义
#define Speed 1

// 共享内存相关常量
#define SHARED_MEM_NAME L"Global\\MySpeedSharedMem"
#define SHARED_MEM_SIZE sizeof(double)

// 共享内存指针
static double* g_sharedSpeed = nullptr;

// 函数声明
void DXSetvalue(int name, double d);
double DXGetvalue(int name);
bool initSharedMemory();
void cleanupSharedMemory();

DataExchange.cpp(新增实现文件)

#include "DataExchange.h"

bool initSharedMemory() {
    // 创建或打开共享内存文件映射
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // 使用分页文件
        NULL,                    // 默认安全属性
        PAGE_READWRITE,          // 读写权限
        0,                       // 高32位大小
        SHARED_MEM_SIZE,         // 低32位大小
        SHARED_MEM_NAME);        // 共享内存名称

    if (hMapFile == NULL) {
        printf("CreateFileMapping failed: %d\n", GetLastError());
        return false;
    }

    // 将共享内存映射到当前进程的虚拟地址空间
    g_sharedSpeed = (double*)MapViewOfFile(
        hMapFile,                // 文件映射句柄
        FILE_MAP_ALL_ACCESS,     // 读写访问
        0,
        0,
        SHARED_MEM_SIZE);

    if (g_sharedSpeed == nullptr) {
        printf("MapViewOfFile failed: %d\n", GetLastError());
        CloseHandle(hMapFile);
        return false;
    }

    // 初始化值(只有第一个创建共享内存的进程需要初始化)
    if (GetLastError() != ERROR_ALREADY_EXISTS) {
        *g_sharedSpeed = 0.5;
    }

    // 可以关闭文件映射句柄,映射的内存依然有效
    CloseHandle(hMapFile);
    return true;
}

void cleanupSharedMemory() {
    if (g_sharedSpeed != nullptr) {
        UnmapViewOfFile(g_sharedSpeed);
        g_sharedSpeed = nullptr;
    }
}

void DXSetvalue(int name, double d) {
    if (g_sharedSpeed == nullptr) {
        printf("Shared memory not initialized!\n");
        return;
    }
    switch (name) {
        case Speed:
            *g_sharedSpeed = d;
            break;
        default:
            printf("未设置地址!!!\n");
    }
}

double DXGetvalue(int name) {
    if (g_sharedSpeed == nullptr) {
        printf("Shared memory not initialized!\n");
        return 0.0;
    }
    switch (name) {
        case Speed:
            return *g_sharedSpeed;
        default:
            printf("未设置地址!!!\n");
            return 0.0;
    }
}

修改后的Program1.cpp

#include <iostream>
#include <windows.h>
#include "DataExchange.h"
using namespace std;

int main(int argc, char** argv) {
    if (!initSharedMemory()) {
        cout << "初始化共享内存失败" << endl;
        return 1;
    }

    double val2 = 0;
    double spd = 1;
    cout << "Program1" << endl;
    
    while (1) {
        DXSetvalue(Speed, spd);
        val2 = DXGetvalue(Speed);
        cout << "[speed] = " << spd++ << " [获取到的speed值] = " << val2 << "\r";
        Sleep(2000); // 2秒
    }

    cleanupSharedMemory();
    return 0;
}

修改后的Program2.cpp

#include <iostream>
#include <windows.h>
#include "DataExchange.h"
using namespace std;

int main(int argc, char** argv) {
    if (!initSharedMemory()) {
        cout << "初始化共享内存失败" << endl;
        return 1;
    }

    double t = 0;
    double val = 0;
    cout << "Program2" << endl;
    
    while (1) {
        t += 2;
        val = DXGetvalue(Speed);
        cout << "(" << t << "秒) " << "[Speed] = " << val << "\r";
        Sleep(2000);
    }

    cleanupSharedMemory();
    return 0;
}

关键说明

  1. 共享内存名称:使用Global\\前缀可以让不同会话(比如服务和桌面进程)的进程也能访问,普通进程可以去掉Global\\,直接用L"MySpeedSharedMem"。
  2. 内存映射:MapViewOfFile会把共享物理内存映射到当前进程的虚拟地址空间,两个进程的虚拟地址可能不同,但指向的是同一块物理内存,所以修改会同步。
  3. 错误处理:代码中加入了基本的错误检查,方便排查问题。
  4. 清理资源:程序退出时调用UnmapViewOfFile释放映射的虚拟地址空间。

内容的提问来源于stack exchange,提问作者Ting-Wei Chien

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:13:16