首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有结构数组的共享内存

具有结构数组的共享内存
EN

Stack Overflow用户
提问于 2015-12-30 18:00:09
回答 3查看 5.4K关注 0票数 0

我使用一个结构数组在两个进程之间共享数据。当我试图将共享内存访问到父进程时,3秒后的程序将引发Segmentation fault错误。为什么数据不能正确共享?

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define LEN     3

typedef struct {
    int val;
} val_t;

int
main (int argc, char *argv[])
{
    key_t   key;
    int     shmid, i, size;
    val_t   **val;

    if ((key = ftok(argv[0], 'D')) == -1) {
        perror("ftok");
        exit(1);
    }

    size = sizeof(val_t *) * LEN;

    if (fork() == 0) {
        if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
            perror("shmget");
            exit(1);
        }

        val = (val_t **) shmat(shmid, 0, 0);
        if (val == (val_t **)(-1)) {
            perror("shmat");
            exit(1);
        }

        for (i = 0; i < LEN; i++) {
            val[i] = (val_t *) malloc(sizeof(val_t));
            val[i]->val = i;
        }

        while (val[0]->val != 3)
            sleep(1);

        if (shmdt(val) == -1) {
            perror("shmdt");
            exit(1);
        }
        shmctl(shmid, IPC_RMID, NULL);
    }
    else {
        sleep(3);

         if ((shmid = shmget(key, size, IPC_EXCL)) == -1) {
            perror("shmget");
            exit(1);
        }

        val = (val_t **) shmat(shmid, 0, 0);
        if (val == (val_t **)(-1)) {
            perror("shmat");
            exit(1);
        }

        printf("%d\n", val[0]->val);
        val[0]->val = 3;

        if (shmdt(val) == -1) {
            perror("shmdt");
            exit(1);
        }
    }

    return 0;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-12-30 19:21:23

问题是,您没有共享结构数组,而是共享指向结构的指针数组,这些指针指向使用malloc分配的非共享内存。您需要的代码更像:

代码语言:javascript
运行
复制
val_t   *val;
size = sizeof(val_t) * LEN;

if (fork() == 0) {
    if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
        perror("shmget");
        exit(1); }

    val = (val_t *) shmat(shmid, 0, 0);
    if (val == (val_t *)(-1)) {
        perror("shmat");
        exit(1); }

    for (i = 0; i < LEN; i++) {
        val[i].val = i; }

也就是说,使用一个结构数组,而不是一个指向结构的指针数组。

请注意,这只有在结构(因此是共享内存)中没有任何指针的情况下才能工作--即使指针指向共享内存,它也可能位于不同进程中的不同地址。

票数 2
EN

Stack Overflow用户

发布于 2015-12-30 18:11:01

您希望在进程之间共享struct,但是您只共享指向结构的指针。如果指向在分叉之前分配和初始化的struct,那么它们在两个进程中都是有效的,但是指向structs的不同副本(malloc()只分配私有内存,从未共享)。然而,实际上,指针仅在执行malloc()的子节点中有效。

因此,不要分配一个指针数组,而是分配一个结构数组:

代码语言:javascript
运行
复制
val_t *val;

/* ... */

size = sizeof(val_t) * LEN;

/* ... */

val = (val_t *) shmat(shmid, 0, 0);

此外,如果您是这样做的,则不需要malloc() (或free())单独的struct

票数 1
EN

Stack Overflow用户

发布于 2015-12-30 18:57:42

在……里面,

代码语言:javascript
运行
复制
val = (val_t **) shmat(shmid, 0, 0);

val指向共享内存中类型为val_t*的数组。这可以在附加到同一个共享内存段的另一个进程中访问。

但在,

代码语言:javascript
运行
复制
val[i] = (val_t *) malloc(sizeof(val_t));

val[i]指向由malloc()分配的内存,这是一个进程的私有内存。不能在其他进程中访问此指针。因此,当您在子进程中执行此操作时,将出现Segmentation fault

代码语言:javascript
运行
复制
val[0]->val = 3;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34534683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档