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

Posted

技术标签:

【中文标题】访问共享进程内存时出现分段错误(核心转储)【英文标题】:Segmentation fault (core dumped) when accessing shared process memory 【发布时间】:2019-05-02 17:06:52 【问题描述】:

我试图让两个子进程将两个随机整数写入共享内存,然后让父进程读取它们。 我似乎无法验证写入,因为每当我尝试访问父进程中的数组元素时都会遇到分段错误。

在写入后立即尝试从子进程中的内存读取什么都不做。

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main()
  srand(time(NULL)); 
  int pid2;
  key_t key = 12345;
  int shmid = shmget(key, 2 * sizeof(int), IPC_CREAT|IPC_EXCL|0666);
  int *array = (int *)shmat(shmid, 0, 0);
  int pid1 = fork();
//write first array element
  if (pid1 == 0)
    int n1 = rand() % 10;
    printf("I'm process number 1, my pid is %d and my number is %d\n", getpid(), n1);
    array[0] = n1;
    return 1;
  
  if (pid1 > 0)
    int pid2 = fork();
    if (pid2 == 0)
//write second array element
      int n2 = rand() % 10;
      printf("I'm process number 2, my pid is %d and my number is %d\n", getpid(), n2);
      array[1] = n2;
      return 1;
    
  
  waitpid(pid1, NULL, 0);
  waitpid(pid2, NULL, 0);
//segmentation fault happens here
  printf("%d\n", array[0]);
  return 0;

【问题讨论】:

关于:int pid2 = fork(); 这使得pid2 成为一个局部变量,与pid2 的初始声明和后面的引用完全无关:waitpid(pid2, NULL, 0); 这是一个需要更正的严重错误.建议:将:int pid2 = fork(); 替换为 pid2 = fork();,以便它使用“函数范围”变量实例,而不是仅在当前代码块中可见的变量 在父进程退出之前,它应该调用shmdt()来分离通过shmat()附加的共享内存 函数:fork() 有 3 个不同的返回值:代码无法检查返回值 fork() 总是成功的。这是一个非常冒险的假设,代码不应该做出 @user3629249 错过了,谢谢! 【参考方案1】:

您没有检查来自 shmget 的有效返回值。

if (shmid<0)printf("shmget error");exit(1);;

如果你这样做了,你会发现分配是无效的,因为那个 key_t 已经存在,尝试另一个 - 或者生成你自己唯一的一个:

key_t key = 1; 

key_t key = ftok("megasuperrandom",'a');

根据“man ftok”:

通常,尽力而为的尝试结合给定的 proj_id 字节, inode 编号的低 16 位和 inode 编号的低 8 位 设备编号转换为 32 位结果。很容易发生碰撞,因为 /dev/hda1 上的文件和 /dev/sda1 上的文件之间的示例。

因此,您可能希望循环遍历一些,直到找到一个可行的方法,作为使用 ftok() 的替代方法。

此外,如果您希望孩子们提出不同的随机数,您可能需要使用不同的随机函数,或者将 srand() 移动到每个孩子。

另外,您可能需要检查“man waitpid”。它不会等到进程退出,它只会等待状态发生变化——这是不可预测的。如果要确保进程退出,则必须检查返回状态。

【讨论】:

奇怪的是,我给 ftok 的字符串似乎没有停止分段错误,但 key_t key = 1; 修复了它。谢谢!

以上是关于访问共享进程内存时出现分段错误(核心转储)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

在Linux机器上运行C代码时出现分段错误(核心转储)[关闭]

运行我的代码时出现分段错误(核心转储)问题

尝试声明大数组时出现分段错误和核心转储[重复]

在opencv c ++中查找图像卷积时出现分段错误(核心转储)错误