2012-10-05 40 views
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; 
} 

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

+0

试图在此发布建议,但格式看起来很可怕..请参阅下面的可能答案。 –

回答

2

在你的代码,你不包括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返回值转换成一int *也将隐藏这样的警告:

warning: assignment makes pointer from integer without a cast 

什么可以在这里发生的是,由于shmat没有定义,编译器会隐有它返回一个int,而不是void *的。如果它返回的地址不符合带符号的整数,则会得到一个整数溢出,这是未定义的行为,并且很可能会导致分段错误以访问未分配的内存位置。

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

+0

这样摆脱了分段错误,谢谢!但是,当我取消注释(来自上面的代码)的打印语句时,我得到了“0”而不是我试图放入的“10”。 – user1723361

+0

@ user1723361:您正在打印'shm_front',而不是'shm_end',它是'10'。 – netcoder

+0

+1。你是对的。如果它是一个64位版本,那么它几乎肯定会崩溃,因为32位int返回应该是一个64位指针。 –

0

这是真的打算作为一个细化的问题,但格式引爆它,并使它无法读取,所以我将其移动到一个答案......

也许我只是在看这个斜眼,但我不会把指针如下:

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

第一个整数会等存储在块的头,就在shm_front,然后下了线......除非共享内存块包含一些相关的信息在偏移量0处,我不知道你为什么会将这些信息分别抵消一个......只是一个观察。

+0

我的意思是“前端”和“结束”是指存储在shm_array中的队列数组。他们会像索引一样进入阵列。 – user1723361

+0

队列的前端和尾端?所以前面/结尾会指向相同的位置,最初,对吗? –

1

我不知道如果这是你唯一的问题,但此行

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

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

一般来说,我发现共享段的现代接口shm_open,使用起来更容易。它的工作原理类似于文件打开和映射,并且对分段大小的限制较少。

+0

很棒!因为我使用结构体= P来映射我的共享内存的原因,我自己也不认识它:)(自我抱怨) –

+0

#5(也许#4)一个sizeof =减少错误的几率。 – WhozCraig

+0

对,我想为阵列分配足够的空间。我会解决这个问题。 – user1723361