这行 C 代码对哈希映射实现做了什么?



在工作中,我们一直在试图弄清楚这段代码的作用,我们觉得它可能会导致问题。这是 C 语言中的哈希图实现。

static thrift_map_node_t *thrift_map_newnode (thrift_map_base_t *m, union keyDataTypes key, void * value, int vsize)
thrift_map_node_t *node;
int ksize = strlen(key) + 1;
int voffset = ksize + ((sizeof(void*) - ksize) % sizeof(void*));
node = malloc(sizeof(*node) + voffset + vsize);
if (!node) return NULL;
memcpy(node + 1, key, ksize);
node->hash = thrift_hash(key);
node->value = ((char*) (node + 1)) + voffset;
memcpy(node->value, value, vsize);
return node;

我们认为问题就在这里

int voffset = ksize + ((sizeof(void*) - ksize) % sizeof(void*));

我们认为这可能会产生负值,例如 C 中的 -9 % 4 = -1。

变通方法或对此尝试执行的操作的任何帮助都会很好。

不,如果size_t的排名高于或等于int永远不会产生负值(它确实如此,除了在一些真正具有 16 位整数的 32 位寻址系统上(,因为

sizeof (void*) - ksize

将属于无符号类型且始终为正数的size_t类型。因此,如果 void 指针宽 8 个字节,ksize 为 17,则减法的结果为(size_t)-9或 64 位机器上的18446744073709551607。模 8 是 7,加到 17 将导致 24,这是sizeof (void *)的倍数。

但是,这依赖于sizeof (void *)2 的幂,因此如果您使用

sizeof (void*) - (ksize + sizeof (void*)) % sizeof (void *)

对于填充,因为这完全避免了负数


确实如此,但结果减法符号的,因为 C99 模数总是负数:例如(-3) % 4-3

顺便说一句,代码不应该使用sizeof (void *),而是_Alignof (void *).


代码中还有一件可疑的事情。假设有人实际上可以输入长度超过 2 GiB 的字符串 - 那么在大多数平台上都会发生签名溢出,这不会很漂亮!

最新更新