Linux 共享内存分段错误

Posted

技术标签:

【中文标题】Linux 共享内存分段错误【英文标题】:Linux Shared Memory Segmentation Fault 【发布时间】:2016-07-15 06:03:31 【问题描述】:

我正在学习共享内存,并创建了这个示例程序来测试一下

//IPC - Shared Memory

#include<stdio.h>
#include<stdlib.h>
#include<linux/ipc.h>
#include<linux/msg.h>
#include<linux/shm.h>

int main(int argc, char* argv[])

  printf("setting up shared memory\n");

  key_t ipc_key;
  int shmid;
  int pid;


  ipc_key = ftok(".",'b');

  if((shmid=shmget(ipc_key, 32, IPC_CREAT|0666))==-1)
  
    printf("error creating shared memory\n");
    exit(1);
  

  printf("shared memory created with id %d\n",shmid);

  //fork a child process
  pid = fork();
  printf("fork result %d\n",pid);
  if(pid==0)
  
    //child process
    //attach the shared memory
    int* shm_add_child = (int*)shmat(shmid, 0,0);
    printf("child attached to shared mem at address %p\n",(void*)shm_add_child);

    while(1)
    
      printf("%d\n",*shm_add_child);
      printf("a\n");
    

    //detach from shm
    shmdt(shm_add_child);
  
  else
  
    //parent process
    int* shm_add_parent;

    shm_add_parent = (int*)shmat(shmid, 0,0);
    printf("parent attached to shared mem at address %p\n",(void*)shm_add_parent);
    *shm_add_parent = 10;

    sleep(10);

    //detach from shm
    shmdt(shm_add_parent);
  

  //remove shm
  shmctl(shmid, IPC_RMID,0);

  exit(0);

但是当我运行它时,我得到了分段错误。看来我指向共享内存的指针不正确。子进程中的无限while循环也没有打印任何内容。

ankit@ankit-ThinkPad-W530:~/Desktop/week1_tasks$ ./ipc_sharedmem_a 
setting up shared memory
shared memory created with id 5996570
fork result 8703
parent attached to shared mem at address 0xffffffff991aa000
fork result 0
child attached to shared mem at address 0xffffffff991aa000
Segmentation fault (core dumped)

这里出了什么问题?

【问题讨论】:

【参考方案1】:

我不确定您为什么要包含最后三个头文件。它们不是正确的标题,并且会给您错误的 shm 函数定义。在我的系统上,gcc 甚至会产生一个警告,提示存在问题:

test.c:38:26: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     int* shm_add_child = (int*)shmat(shmid, 0,0);
                          ^
test.c:55:22: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     shm_add_parent = (int*)shmat(shmid, 0,0);

相反,您应该只包含shmat man page 中指定的那些。具体来说:

#include<stdio.h>
#include<stdlib.h>

// Remove these headers
//#include<linux/ipc.h>
//#include<linux/msg.h>
//#include<linux/shm.h>

// Include these instead
#include <sys/types.h>
#include <sys/shm.h>

【讨论】:

感谢您指出这一点。我也对此感到困惑。但我遵循的教程包括 linux 的,所以我选择了那些。两者到底有什么区别? 我不知道这些标题到底是什么。它们看起来像内核和库内部使用的头文件。 包括提到的标题,消除了警告,但分段错误问题仍然存在

以上是关于Linux 共享内存分段错误的主要内容,如果未能解决你的问题,请参考以下文章

尝试锁定共享内存互斥体时出现分段错误

使用共享内存时出现分段错误

访问共享进程内存时出现分段错误(核心转储)

通过共享内存和管道的 IPC 给出分段错误:C 中的 11

如何制作具有特定数组大小的共享内存?

C:更新共享内存 pthread 并使用 strncpy