2

我正在尝试创建一个包含三个整数和一个数组的共享内存段。该段已创建并附加了一个指针,但是当我尝试访问变量的值(无论是更改、打印等)时,我遇到了分段错误。

这是我尝试过的代码:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define SIZE 10

    int* shm_front;
    int* shm_end;
    int* shm_count;
    int* shm_array;
    int shm_size = 3*sizeof(int) + sizeof(int[SIZE]);

int main(int argc, char* argsv[])
{
    int shmid;

    //create shared memory segment
    if((shmid = shmget(IPC_PRIVATE, shm_size, 0644)) == -1)
    {
        printf("error in shmget");
        exit(1);
    }

    //obtain the pointer to the segment
    if((shm_front  = (int*)shmat(shmid, (void *)0, 0)) == (void *)-1)
    {
        printf("error in shmat");
        exit(1);
    }
    //move down the segment to set the other pointers
    shm_end = shm_front + 1;
    shm_count = shm_front + 2;
    shm_array = shm_front + 3;

//tests on shm
*shm_end = 10;                //gives segmentation fault
printf("\n%d", *shm_end);   //gives segmentation fault

           //clean-up
    //get rid of shared memory
    shmdt(shm_front);
    shmctl(shmid, IPC_RMID, NULL);

    printf("\n\n");
    return 0;
}

我尝试通过取消引用指向结构的指针来访问共享内存,但每次都出现分段错误。

谢谢大家,现在没有分段错误。

4

3 回答 3

2

在您的代码中,您没有 include sys/shm.h,这应该会导致您的编译器吐出这些:

warning: implicit declaration of function ‘shmget’
warning: implicit declaration of function ‘shmat’
warning: implicit declaration of function ‘shmdt’
warning: implicit declaration of function ‘shmctl’

将返回值shmat转换为 anint *也会隐藏此警告:

warning: assignment makes pointer from integer without a cast

这里可能发生的情况是,由于shmat未定义,编译器将隐式让它返回 anint而不是 a void *。如果它返回的地址不适合有符号整数,则会出现整数溢出,这是未定义的行为,并且很可能会导致访问未分配的内存位置时出现分段错误。

您不应该强制转换专门返回的函数的返回值void *来捕获这些错误(并且始终在启用警告的情况下进行编译)。

于 2012-10-05T15:35:57.393 回答
1

我不知道这是否是您唯一的问题,但这条线

int shm_size = 3*sizeof(int) + sizeof(shm_array[SIZE]);

很可能不是你想要的。sizeof(shm_array[SIZE])只是一个int而不是数组的大小。如果你想要,你应该使用sizeof(int[SIZE]).

通常,我发现共享段的现代界面shm_open更易于使用。它的工作方式类似于文件打开和映射,并且对段大小的限制较少。

于 2012-10-05T15:31:20.007 回答
0

这实际上是一个细化问题,但是格式化程序将其炸毁并使其无法阅读,因此我将其移至答案...

也许我只是在看这个问题,但您的指示不会如下:

shm_end = shm_front;
shm_count=shm_front+1
shm_array=shm_front+2; 

第一个整数将存储在块的头部,就在 shm_front,然后依次类推……除非共享内存块在偏移量 0 处包含一些相关信息,否则我不知道你为什么要偏移这些一个……只是一个观察。

于 2012-10-05T15:26:14.217 回答