从共享内存获取数组时触发段错误的问题排查
共享内存段错误原因及修复方案
问题根源
- shmget权限参数缺失:调用
shmget时仅传入IPC_CREAT,未指定权限位(如0666),导致创建的共享内存权限异常,后续shmat可能返回无效地址(void*)-1,对该地址操作直接触发段错误。 - 未检查shmat返回值:没有判断共享内存映射是否成功,直接使用返回指针,一旦映射失败就会操作非法内存。
- 冗余的memcpy操作:直接赋值
array[i] = array_copy[i]即可完成数据写入,没必要用memcpy增加代码复杂度。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> int main(int argc, char const *argv[]) { int *array; int shmid; // 添加权限位0666,确保共享内存可正常映射 shmid = shmget(1234, 3 * sizeof(int), IPC_CREAT | 0666); if (shmid == -1) { perror("shmget error"); exit(EXIT_FAILURE); } // 检查shmat映射是否成功 array = (int*)shmat(shmid, NULL, 0); if (array == (void*)-1) { perror("shmat error"); exit(EXIT_FAILURE); } int array_copy[3]; int i; for (i = 0; i < 3; i++) { array_copy[i] = i; // 直接赋值替代memcpy array[i] = array_copy[i]; } for (i = 0; i < 3; i++) printf("\n nm: %d and array: %d", array_copy[i], array[i]); shmdt((void *)array); return 0; }
额外说明
- 共享内存创建时必须指定权限位,否则其他进程(甚至当前进程)可能无法正常访问该内存段。
- 所有IPC系统调用(
shmget、shmat、shmdt等)都应该检查返回值,这是排查问题的关键。 - 若后续需要彻底删除共享内存,可调用
shmctl(shmid, IPC_RMID, NULL),否则该内存段会一直留存于系统中,直到重启或手动清理。
内容的提问来源于stack exchange,提问作者Matteo Pagliarello
相关产品推荐
相关产品推荐

