c-使用灵活数组成员的奇怪行为



我试图使用更为普遍接受的习惯用法:将结构的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 %dn", entry->counter); // returns 1, reliably
    return entry->block; // Gives me gibberish but not if I uncomment void* block2.
}

这有什么原因吗?我不一定认为我在任何地方都会踩东西,而且它过去一直采用"无效"的方法奇怪的是,如果我把一个伪void*放回结构中,它就会工作。如果我放入一个伪int.,它就不起作用

编辑:实际上,如果AddEntry中的number不为0,也会失败。如果有什么不同的话,我在踩什么?

您的问题在这里:

&memPtr[number]

由于memPtr是一个void *指针,所以在C中根本不允许这样做。一些编译器确实允许将void *指针上的算术作为语言扩展,但他们将其视为char *指针。

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

您的分配行似乎假设每个Entry有1024个字节(如果someSize是多个Entry结构),所以您可能想要这样的东西:

((char *)memPtr + number * 1024)

(类似于returnBlock()函数)。

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

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

相关内容

  • 没有找到相关文章

最新更新