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

共享内存父进程无权限求助:shmat返回-1引发段错误

C语言共享内存shmat权限被拒及段错误问题

问题现象

父进程调用shmat返回-1,提示Permission denied,后续对指针解引用触发段错误;子进程shmat同样返回(void*) -1,但因未对指针操作而正常退出。原本预期父子进程均可正常挂载并操作共享内存。

代码实现

#include "sys/ipc.h"
#include "sys/shm.h"

#include "unistd.h"
#include "sys/types.h"
#include "sys/wait.h"

#include "stdio.h"
#include "stdlib.h"

int main(){
    key_t key = ftok("shmfile.txt", 65);
    int shmid = shmget(key, sizeof(int), IPC_CREAT);
    if (fork() != 0){
        int * ptr = (int *) shmat(shmid, 0, 0); // 该行返回-1,仅父进程出现此情况
        printf("shmid parent = %d\n", shmid);
        perror("Error ");
        *ptr = 6;
        shmdt(ptr);
        wait(NULL);
        shmctl(shmid, IPC_RMID, NULL);
    }
    else{
        printf("shmid child = %d\n", shmid);
        int * ptr = (int *) shmat(shmid, 0, 0); // 符合预期运行
        printf("ptr address = %p\n", ptr);      
        shmdt(ptr);
        printf("Now child can exit normally");
    }
    return 0;
}

GDB调试输出

shmid parent = 45
Error : Permission denied
shmid child = 45
ptr address = 0xffffffffffffffff
Now child can exit normally
Program received signal SIGSEGV, Segmentation fault.
0x00005555555552d0 in main () at main_2.c:20
20          *ptr = 6;

更新信息

  • 更新1:父进程与子进程的ptr均为(void *) -1,无法让shmat返回正常值
  • 更新2:shmfile.txt与可执行文件main位于同一目录

解决方案

1. 修复shmget权限参数

shmget创建共享内存时必须指定权限掩码,否则默认权限会导致进程无法挂载。修改shmget调用,在IPC_CREAT后添加权限位(例如0666,表示所有用户可读可写,可根据需求调整):

int shmid = shmget(key, sizeof(int), IPC_CREAT | 0666);

2. 添加shmat返回值检查

在使用shmat返回的指针前,必须检查是否挂载成功,避免对无效指针操作引发段错误:

int *ptr = (int *)shmat(shmid, 0, 0);
if (ptr == (void*)-1) {
    perror("shmat failed");
    exit(EXIT_FAILURE);
}

原因说明

  • 未指定权限位的共享内存,默认权限极低,导致进程没有挂载权限,shmat返回-1。
  • 子进程未触发段错误,是因为它没有执行*ptr = 6;这样的指针解引用操作,而父进程对无效指针赋值直接触发了SIGSEGV信号。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 09:40:29