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
相关产品推荐
相关产品推荐

