首页 文章

使用灵活阵列成员的奇怪行为

提问于
浏览
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 方法 . The weird thing is that if I put a dummy void back into the struct, it works . 如果我输入一个虚拟int,它就不起作用 .

编辑:实际上,如果 AddEntry 中的 number 不是0,它也会失败 . 如果有的话,我该踩什么?

1 回答

  • 2

    你的问题在这里:

    &memPtr[number]
    

    由于 memPtrvoid * 指针,因此C中实际上不允许这样做 . 有些编译器允许将 void * 指针上的算术作为语言扩展 - 但是它们将它视为 char * 指针 .

    这意味着 &memPtr[number] 可能只将 number 字节索引到您的内存块中 - 因此复制的第二个 Entry 结构将与第一个重叠,依此类推 .

    您的分配行似乎假设每个 Entry 有1024个字节(如果 someSizeEntry 结构的数量),那么您可能需要以下内容:

    ((char *)memPtr + number * 1024)
    

    (和 returnBlock() 函数中的类似) .

    但是,如果你这样做,你会注意到使用灵活的数组成员没有意义 - 因为你正在创建这些结构的连续数组,并且没有单独的索引,你必须假设每个都是一个固定大小 . 这意味着你不妨让每个人都有一个固定的大小:

    typedef struct Entry {
        int counter;
        unsigned char block[1024 - sizeof counter];
    }
    

相关问题