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 它将不起作用。

编辑:实际上,如果numberinAddEntry不是 0,它也会失败。我踩的是什么,如果有的话?

4

1 回答 1

2

你的问题在这里:

&memPtr[number]

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

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

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

((char *)memPtr + number * 1024)

returnBlock()功能类似)。

However, if you do this you will notice that there is no point in using the flexible array member - because you're creating a contiguous array of these structures, and don't have a separate index, you have to assume each one is a fixed size. This means that you might as well make each one a fixed size:

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