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

C语言SysV共享内存映射自定义结构体及访问动态长度缓冲区问题

解决方案

问题根源

你的原有实现存在两个核心问题:

  • 结构体中的char* buffer是指针类型,你没有对它赋值就直接访问,必然触发内存错误。即便你在当前进程完成赋值,跨进程使用时不同进程挂载共享内存的基地址可能不同,存储在共享内存中的指针也会直接失效。
  • 原有代码中shmat(*shmid, NULL, 0)写法错误,shmid是shmget返回的整数ID,不需要解引用。

推荐方案:使用C99柔性数组成员

这是共享内存自定义结构体的标准实现方式,柔性数组成员必须放在结构体末尾,不会占用结构体的存储空间,地址刚好紧跟在结构体最后一个固定成员之后,完全匹配你的需求,且不存在跨进程地址失效问题。

代码实现

// 结构体定义,最后一位为柔性数组成员
struct shared_memory_t {
    int value1; 
    int value2;
    char buffer[]; 
};

// 申请共享内存,总大小=结构体固定大小 + 缓冲区大小segsize
shmid = shmget(key, sizeof(struct shared_memory_t) + segsize, 0666|IPC_CREAT);
if (shmid == -1) {
    // 补充你的错误处理逻辑
}

// 挂载共享内存
struct shared_memory_t* mem = (struct shared_memory_t*) shmat(shmid, NULL, 0);
if (mem == (void*)-1) {
    // 补充你的错误处理逻辑
}

使用方式

  • 访问结构体成员:直接用mem->value1、mem->value2读写即可
  • 访问后续缓冲区:直接使用mem->buffer即可,它的起始地址刚好是两个int成员之后的共享内存位置,可以当成大小为segsize的char数组正常读写。

兼容方案:手动计算偏移(仅适用于单进程场景)

如果你的编译环境不支持C99标准,可以用手动赋值指针的方式实现,注意该方案的指针是当前进程地址空间的地址,跨进程使用会失效。

代码实现

struct shared_memory_t {
    int value1; 
    int value2;
    char* buffer; 
};

shmid = shmget(key, sizeof(struct shared_memory_t) + segsize, 0666|IPC_CREAT);
if (shmid == -1) {
    // 错误处理
}

struct shared_memory_t* mem = (struct shared_memory_t*) shmat(shmid, NULL, 0);
if (mem == (void*)-1) {
    // 错误处理
}

// 手动给buffer指针赋值,指向结构体末尾之后的地址
mem->buffer = (char*)mem + sizeof(struct shared_memory_t);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:24:06