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

标签 c interprocess

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

写入后立即尝试从子进程中的内存中读取不会执行任何操作。

#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;
}

最佳答案

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

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

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

key_t key = 1; 

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

根据“man ftok”:

Typically, a best-effort attempt combines the given proj_id byte, the lower 16 bits of the inode number, and the lower 8 bits of the device number into a 32-bit result. Collisions may easily happen, for example between files on /dev/hda1 and files on /dev/sda1.

因此,您可能想要循环一些直到找到一个有效的,作为使用 ftok() 的替代方法。

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

此外,您可能想检查“man waitpid”。它不会等到进程退出,它只等待更改的状态 - 这是不可预测的。如果您想确保进程已退出,则必须检查返回状态。

关于c - 访问共享进程内存时出现段错误(核心转储),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55957194/

相关文章:

c - 在 C 中使用管道进行父子 IPC 会使程序阻塞

c - 为什么我们这里使用 "&"(: insert(&(*root)->left,值);但我们这里不使用 "&": search(root->left,值);

boost::Windows 服务和用户应用程序之间的进程

c - 需要在线程任务中正确使用 sleep()

c - 有没有一种方法可以启动另一个程序而不必执行 fork()?

c# - 如何在 C# 中正确使用命名管道——多个连接、服务器重建等

c++ - 异步c++进程间控制

c# - Process.Start 与 C# 中的 Process `p = new Process()`?

c - 如何在C中将负零转换为正零?

c - 编译使用 libvncserver 的项目时出错