You need to enable JavaScript to run this app. 调用shmat()返回invalid argument错误,共享内存读取异常排查
优惠活动
大模型
产品
解决方案
定价
更多

调用shmat()返回invalid argument错误,共享内存读取异常排查

共享内存shmat报EINVAL(Invalid argument)的根因与修正

直接定位的代码错误(按影响优先级排序)

  • 运算符优先级写错导致shmid赋值完全失效
    C语言中关系运算符<的优先级远高于赋值运算符=,当前代码中if (shmid = shmget(key, MAX * sizeof(data),0666) < 0)的实际执行逻辑是:
    1. 先执行shmget拿到合法的正整数共享内存id
    2. 将该id与0做布尔比较,得到结果0
    3. 把比较结果0赋值给shmid
      后续传给shmat的shmid值恒为0,根本不是内核返回的合法共享内存标识符,系统校验参数不通过,直接返回Invalid argument错误。
  • 指针类型声明逻辑完全错误
    代码里data *dados[MAX]本质是包含MAX个data类型指针的数组,不是指向连续共享内存块的单指针。把shmat返回的映射地址赋值给数组第一个元素*dados后,后续用dados[i]->id的方式访问内存,本质是读取数组里每个未初始化的野指针指向的地址,哪怕shmat调用成功,也会触发段错误。
  • shmat报错后未做退出处理
    原代码shmat执行失败后没有return,会继续执行后续循环逻辑,访问无效内存区域,叠加报错现象。

修正后的可运行代码

#include <stdio.h>
#include <sys/shm.h>
#include <stdlib.h>

#define MAX 10 // 需与写入端定义的MAX值保持一致
typedef struct
{
    long id;
} data;

// 正确声明:指向连续共享内存块的单结构指针,而非指针数组
data *dados;

int main()
{
    key_t key = 5678;
    int shmid;

    // 加括号明确执行顺序:先完成shmid赋值,再判断返回值是否小于0
    if ((shmid = shmget(key, MAX * sizeof(data), 0666)) < 0)
    {
        perror("shmget error");
        return 1;
    }

    // 直接将shmat返回的映射地址赋值给单指针
    if((dados = shmat(shmid, NULL, 0)) == (void*) -1)
    {
        perror("shmat");
        return 1; // 报错后直接退出,避免无效内存访问
    }

    for (int i = 0; i < MAX; i++)
    {
        printf("time:%ld\n", dados[i].id);
        printf("passed %d\n", i);
    }

    // 用完主动解除映射
    shmdt(dados);
    return 0;
}

额外校验排查项

  • 执行ipcs -m查看系统当前共享内存块列表,确认key=5678对应的块真实存在,块大小与两端约定的MAX * sizeof(data)一致
  • 确认shmat的flag参数未传入非法值,默认传0即可
  • 检查写入端是否在创建共享内存后、读取端接入前就执行了IPC_RMID删除操作,被提前删除的共享内存会导致接口校验失败

内容的提问来源于stack exchange,提问作者Filipe Coutinho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.09 07:45:10