首页 文章

Calloc不会将整个内存块初始化为零

提问于
浏览
3

在玩一个hashmap玩具示例的实现(为了好玩)我发现了一个奇怪的行为,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 %d\n", 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不起作用 . 我究竟做错了什么?

1 回答

  • 3
    my_dict->items = calloc(DICT_INITIAL_CAPACITY, sizeof my_dict->items);
    

    应该

    my_dict->items = calloc(DICT_INITIAL_CAPACITY, sizeof *my_dict->items);
    

    另请注意,通常, calloc 可能不会将指针设置为null(尽管它在我所知道的所有现代系统上都有) . 显式初始化任何意味着为null的指针会更安全 .

    话虽如此,你似乎存储了一个 size 变量来表示字典的大小,所以你可以通过不读取当前 size 之外的条目来完全避免这个问题;当你增加 size 然后初始化你刚刚添加的条目 .

相关问题