我尝试使用更容易接受的习惯用一个灵活的数组成员替换结构的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 *方法。 奇怪的是,如果我将一个虚拟的空白*放回到结构中,它就会起作用。如果我输入一个虚拟的int,它就无法工作。
编辑:实际上,如果number
中的AddEntry
不是0,它也会失败。如果有的话,我该踩什么?
答案 0 :(得分:2)
你的问题在这里:
&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];
}