Calloc不会将整个内存块初始化为零
在玩哈希贴图玩具的例子(为了好玩)时,我发现了一个奇怪的行为,calloc并没有初始化我想要的零的整个内存块,就像应该这样做。 如果整个内存块归零,以下代码不应该输出:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define DICT_INITIAL_CAPACITY 50
typedef struct dictionary_item {
char* ptr_key;
void* ptr_value;
} dict_item;
typedef struct dictionary {
dict_item* items;
uint16_t size, max_capacity;
} Dict;
Dict* dict_new() {
Dict *my_dict = calloc(1, sizeof *my_dict);
my_dict->items = calloc(DICT_INITIAL_CAPACITY, sizeof my_dict->items);
my_dict->size = 0;
my_dict->max_capacity = DICT_INITIAL_CAPACITY;
for (int j = 0; j < my_dict->max_capacity; j++) {
int key_null = 1;
int value_null = 1;
if ((my_dict->items + j)->ptr_key != NULL)
key_null = 0;
if ((my_dict->items + j)->ptr_value != NULL)
value_null = 0;
if ((my_dict->items + j)->ptr_key != NULL || (my_dict->items + j)->ptr_value != NULL)
printf("item %d, key_null %d, value_null %dn", j, key_null, value_null);
}
return my_dict;
}
int main(int argc, char** argv) {
Dict* dict = dict_new();
}
但是它会产生输出:
item 25, key_null 1, value_null 0
唯一的非零项目总是DICT_INITIAL_CAPACITY / 2中的项目。我也尝试使用memset将所有块归零并且结果相同。 如果我明确地使用下面的内容为零:
for (int j = 0; j < my_dict->max_capacity; j++){
(my_dict->items + j)->ptr_key = 0;
(my_dict->items + j)->ptr_value = 0;
}
然后我得到所需的行为。 但我不明白为什么它不能使用calloc。 我究竟做错了什么?
my_dict->items = calloc(DICT_INITIAL_CAPACITY, sizeof my_dict->items);
应该
my_dict->items = calloc(DICT_INITIAL_CAPACITY, sizeof *my_dict->items);
还要注意,一般来说, calloc
可能不会将指针设置为null(尽管它在我所知的所有现代系统上都有)。 显式初始化任何意味着为空的指针会更安全。
话虽如此,您似乎正在存储一个size
变量来指示字典的大小,因此您可以通过不读取超出当前size
条目完全避免此问题; 当你增加size
然后初始化你刚添加的条目。