C++子进程访问共享内存值异常:读取returnLicense结果始终为0
问题根因及修复方案
你代码存在3个核心错误导致共享内存读写不符合预期:
- 指针参数值传递导致主进程的共享内存地址未正确赋值
initSharedMemory函数的入参License *l是值传递,函数内部对l的赋值仅修改了栈上的形参副本,main函数中定义的License *l始终是未初始化的野指针,后续tmp->initLicense(num)属于非法内存访问,结果完全不可预期。
修复方案:将参数改为指针引用,修改函数定义为:
- 指针参数值传递导致主进程的共享内存地址未正确赋值
int initSharedMemory (License *&l) {
- 共享内存申请大小错误
shmget的第二个参数你传入的是sizeof(l),l是指针类型,32位系统下占4字节、64位系统下占8字节,远小于License结构体的实际大小,共享内存根本没有足够空间存储完整的License对象。
修复方案:将两处shmget的大小参数改为sizeof(License):
- 共享内存申请大小错误
// 父进程申请 int shmid = shmget(key, sizeof(License), 0666|IPC_CREAT); // 子进程获取 int shmid = shmget(key, sizeof(License), 0666);
- C++类在共享内存中的使用限制
如果你的License类包含虚函数、std::string/std::vector这类动态分配内存的成员,或者自定义了非平凡的构造/析构函数,直接放到共享内存中跨进程访问必然出错:虚函数表指针、动态内存的指针在不同进程的地址空间中完全无效。
修复方案:确保License是标准布局类型,可以用static_assert(std::is_standard_layout_v<License>, "License must be standard layout");做编译期校验,所有成员都使用固定大小的数组/基础类型,不要包含任何动态内存分配逻辑。
- C++类在共享内存中的使用限制
修正后核心代码示例
// 仅展示修改部分 int initSharedMemory (License *&l) { // 改为指针引用 key_t key = ftok("/tmp", 'J'); cout << "key: " << key << endl; int shmid = shmget(key, sizeof(License), 0666|IPC_CREAT); // 调整申请大小 if (shmid == -1) { perror("Shared memory"); return -1; } l = (License*)shmat(shmid, (void*)0, 0); if (l == (void*) -1) { perror("Shared memory attach"); return -1; } // 额外补充:第一次创建共享内存时主动初始化对象,避免脏数据 new (l) License(); // 定位new显式构造对象 return shmid; }
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

