首页 > 模仿redis字典部分代码:dict.c 疑惑中

模仿redis字典部分代码:dict.c 疑惑中

模仿redis字典部分代码:dict.c
但是会报段错误,疑惑中

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct dictEntry {
    int key;
} dictEntry;

typedef struct dictht {
    dictEntry **table;      
    int d_val;
} dictht;

typedef struct dict {
    dictht ht[2];       
} dict;

dictEntry *dictAddRaw(dict *d, void *key)
{
    dictEntry *entry;

    entry = zmalloc(sizeof(*entry));
} 

zmalloc 和malloc一样,
问题是一般分配内存都是
entry = zmalloc(sizeof(entry));
为什么redis
entry = zmalloc(sizeof(*entry));


假设add_ht传入的参数d已经被初始化,指向已经分配的内存空间,这个时候ht->table是一个指向指针的指针,初始化时候的值为0. ht->table = dict_entry这个语句行dict_entry指针的值付给ht->table, 虽然类型不匹配,一个是指针,一个是指向指针的指针,但是由于ht->table是合法的,所以还不会出现内存访问错误。ht->table[0] 所做的是取ht->table的值(为0),然后加上 0 * sizeof(dict_entry *)的offset,然后将得到的地址作为将要存储dict_entry值的内存地址,类似于下面的操作
*(ht->table + 0 * sizeof(dict_entry *) = dict_entry;
由于这个时候ht->table的值为0,那么这个操作的最终内存地址也是0,这样就产生了内存访问错误。


第3版本,这次应该没问题了

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct dictEntry {
    int key;
} dictEntry;

typedef struct dictht {
    dictEntry **table;      
    int d_val;
} dictht;

typedef struct dict {
    dictht ht[2];       
} dict;

dict *dictCreate();
int dictInit(dict *d);
static void dictReset(dictht *ht);

dict *dictCreate()
{
    dict *d = malloc(sizeof(*d));
    dictInit(d);
    return d;
}

int dictInit(dict *d)
{
    dictReset(&d->ht[0]);
    dictReset(&d->ht[1]);
    return 0;//ok
}

static void dictReset(dictht *ht)
{
    ht->table = malloc(sizeof(dictEntry **));//必须这么写
    ht->d_val = 0;
}

static void add_ht(dict *d,int val)
{
    dictEntry *entry;
    dictEntry *entry0;
    dictht *ht;
    ht = &d->ht[0];

    //现在没有段错误,但是redis 源码的
    //entry = zmalloc(sizeof(*entry));
    entry=malloc(sizeof(*entry));
    entry->key=123;
    ht->table[1]=entry;

    entry0=malloc(sizeof(*entry));
    entry0->key=456;
    ht->table[0]=entry0;

    printf("%d\n",ht->table[1]->key);
    printf("%d\n",ht->table[0]->key);
    return;
}

void add_to_ht(dict *d,int val){
    add_ht(d,val);
}

int main(int argc, const char *argv[])
{
    dict *d;
    d=dictCreate();

    //add
    add_to_ht(d,22);

    return 0;
}


ht->table=dict_entry; 这也不对啊,dict_entry的类型是dict_Entry*
ht->table的类型是dict_Entry**
而且,你也没有为ht分配内存,所以ht->table也不对。

所以,你首先需要为ht分配内存,dictht *ht = malloc(sizeof(dictht));
然后再ht->table = &dict_entry;

或者,直接*(ht->table) = malloc(sizeof(dict_entry)*数组大小)


Edit:

你在那里用sizeof(entry)是不对的,可能你只是碰巧遇到sizeof(entry)的大小和sizeof(*entry)的大小相同。

因为sizeof(entry)得到的是指针的大小,sizeof(*entry)得到的才是dictEntry的大小。用sizeof(*entry)有一个好处就是当你修改entry的类型的时候,你不需要再去修改sizeof里面的东西。

例如:

TypeA* ptr = malloc(sizeof(TypeA));如果要修改ptr为:TypeB* ptr,那么就要连带修改sizeof(TypeA)sizeof(TypeB)。如果用sizeof(*ptr),那么只需要修改把类型改为TypeB

还有,为什么sizeof(*entry)是合法的?

Edit:

或者,直接*(ht->table) = malloc(sizeof(dict_entry)*数组大小)

抱歉,之前这里漏了,要先为ht->table分配内存先。

【热门文章】
【热门文章】