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

Linux Ubuntu下结构体char*成员共享内存操作内存错误问题

问题排查与解决方法

核心问题根因

你的代码存在三个核心错误点:

  • 字符串存储的共享内存段申请大小不足:你申请shmID2时仅分配了4字节的空间,而存储"Alex"、"Romy"这类4个字符的字符串需要额外1字节存储结束符\0,至少需要5字节空间,字符串溢出触发内存访问错误。
  • 共享内存中存储指针的错误用法:指针是进程虚拟地址空间的局部地址,同一个共享内存段在不同进程中映射的虚拟地址可能不同,跨进程传递指针大概率访问到非法地址。你当前代码虽然在SECOND程序中重新对A->msg赋值了当前进程内的映射地址规避了这个问题,但这种写法本身就有极高的出错风险。
  • 缺少系统调用错误校验:所有的ftok、shmget、shmat等系统调用都没有做返回值校验,出现错误时无法快速定位故障点。

排查步骤

  • 给所有系统调用增加返回值判断:每调用一个系统调用后判断返回值是否为错误值(ftok、shmget失败返回-1,shmat失败返回(void*)-1),出错时调用perror打印错误原因,可快速定位是哪一步调用出现问题。
  • 检查共享内存段的大小是否匹配实际存储需求:存储字符串时必须预留结束符\0的存储空间,申请大小为「最大预期字符串长度 + 1」。
  • 检查共享内存的访问权限:确认两个程序运行用户对共享内存段有读写权限,你当前使用的0664权限符可满足同用户、同用户组的读写需求。

修复方案

方案1:最小改动修复现有逻辑

仅修改共享内存段申请大小,增加错误校验:

  • 把START程序中shmID2 = shmget(shmKEY2, sizeof(char)*4, IPC_CREAT | 0664);修改为shmID2 = shmget(shmKEY2, sizeof(char)*16, IPC_CREAT | 0664);(16字节可存储最长15个字符的字符串,可按需调整大小)。
  • 为所有系统调用增加错误判断,示例如下:
shmKEY= ftok(".",'a');
if(shmKEY == -1) {
    perror("ftok失败");
    exit(1);
}
int shmID = shmget(shmKEY,sizeof(struct CHAR),IPC_CREAT | 0664);
if(shmID == -1) {
    perror("shmget失败");
    exit(1);
}
struct CHAR* A = shmat(shmID,NULL,0);
if(A == (void*)-1) {
    perror("shmat失败");
    exit(1);
}

方案2:更稳定的优化方案

直接修改结构体为定长数组,避免共享内存存储指针的风险,同时减少一次共享内存操作,逻辑更简洁:

  1. 修改test.h中的结构体定义:
#ifndef _TEST_H
#define _TEST_H
struct CHAR{
    char msg[16]; // 定长数组,直接存在共享内存段中,无需额外分配
};
#endif
  1. 去掉shmID2相关的所有共享内存操作,仅保留shmID的共享内存段即可,读写A->msg时直接使用字符串操作函数即可,无需额外赋值指针。

内容的提问来源于stack exchange,提问作者Neku Sakuraba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:06:03