1

より受け入れられているイディオムを使用して、構造体のvoid*メンバーを柔軟な配列メンバーに置き換えようとしました。

typedef struct Entry {
    int counter;
    //void* block2; // This used to be what I had
    unsigned char block[1];
}

次に、エントリを連続メモリブロックに追加します。

void *memPtr = mmap(NULL, someSize*1024, PROT_READ|PROT_WRITE, 
                        MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

そのような:

int number = 0;

int AddEntry(void *data) {
   Entry *entry;
   entry = malloc(sizeof(Entry) + ((SECTOR_SIZE-1) * sizeof(unsigned char));
   entry->counter = 1;
   memcpy(entry->block, data, SECTOR_SIZE);

   // make sure number doesn't overflow space, etc...
   memcpy(&memPtr[number], entry, sizeof(Entry) + ((SECTOR_SIZE-1) * sizeof(unsigned char));
   number++;
   return 0;
}

問題は、必要に応じてこのデータを解凍することです。たとえば、私がそうする場合:

void * returnBlock(int i) {
    Entry * entry  = &memPtr[i];
    printf("Entry counter is %d\n", entry->counter); // returns 1, reliably
    return entry->block; // Gives me gibberish but not if I uncomment void* block2.
}

これが考えられる理由はありますか?私は必ずしもどこかで何かを踏みつけているとは思いません、そしてそれはvoid*アプローチで働いていました。奇妙なことに、ダミーのvoid *を構造体に戻すと、機能します。ダミーintを入れても動作しません。

number編集:実際には、 inが0でない場合も失敗します。もしあれば、AddEntry私は何を踏んでいますか?

4

1 に答える 1

2

あなたの問題はここにあります:

&memPtr[number]

memPtrはポインターであるためvoid *、これは実際には C ではまったく許可されていません。一部のコンパイラはvoid *、言語拡張としてポインターの算術演算を許可していますが、ポインターをポインターのように扱いchar *ます。

つまり、メモリ ブロックにバイト&memPtr[number]のみをインデックス付けしている可能性が高いため、コピーされた 2 番目の構造は最初の構造と重複します。number Entry

割り当てラインは、(構造体の数のEntry場合) あたり 1024 バイトを想定しているように見えるため、次のようなものが必要になる可能性があります。someSizeEntry

((char *)memPtr + number * 1024)

(および関数で同様returnBlock())。

ただし、これを行うと、柔軟な配列メンバーを使用する意味がないことに気付くでしょう。これらの構造体の連続した配列を作成していて、個別のインデックスがないため、それぞれが固定サイズ。これは、それぞれを固定サイズにすることもできることを意味します。

typedef struct Entry {
    int counter;
    unsigned char block[1024 - sizeof counter];
}
于 2012-02-27T05:24:46.200 に答える