2

3 つの整数と配列を含む共有メモリ セグメントを作成しようとしています。セグメントが作成され、ポインターがアタッチされますが、変数の値にアクセスしようとすると (変更、印刷など)、セグメンテーション エラーが発生します。

これが私が試したコードです:

#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

あなたのコードには が含まれていませんでした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が定義されていないため、コンパイラは暗黙的にintではなく を返すようにすること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 に関連情報が含まれていない限り、なぜこれらをオフセットするのかわかりません1つずつ...ただの観察です。

于 2012-10-05T15:26:14.217 に答える