【问题标题】:Odd behaviour using flexible array member使用灵活数组成员的奇怪行为
【发布时间】:2012-03-16 14:39:10
【问题描述】:

我尝试使用更广为接受的习语将结构的 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 它将不起作用。

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

【问题讨论】:

  • 您不能创建包含灵活数组成员的结构数组。
  • memptr[i] 到底是什么?您不能为 void 指针下标。
  • 正如@R.. 所说,拥有一个灵活数组的数组是没有意义的。灵活数组成员的所有想法是您拥有数据结构的“标题”部分并且数组本身是连续的。因此,如果您真的需要不同大小的 Entrys,则需要一个指向该类型的指针数组。

标签: c malloc c99 flexible-array-member


【解决方案1】:

你的问题在这里:

&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];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 2011-03-04
    • 1970-01-01
    • 2020-04-13
    相关资源
    最近更新 更多