Как правильно освободить память для данной реализации словаря в С

Необходимо реализовать словарь в Си, в котором ключ и значение являются строками.

Нашел в книжке простой вариант реализации словаря. Но не совсем получается полностью освобождать память после его использования.

#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "string.h"
#include "stdlib.h"


struct nlist { /* table entry: */
    struct nlist* next; /* next entry in chain */
    char* name; /* defined name */
    char* defn; /* replacement text */
};

#define HASHSIZE 1
static struct nlist* hashtab[HASHSIZE]; /* pointer table */

/* hash: form hash value for string s */
unsigned hash(char* s) {
    unsigned hashval;
    for (hashval = 0; *s != '\0'; s++)
        hashval = *s + 31 * hashval;
    return hashval % HASHSIZE;
}

struct nlist* lookup(char* s) {
    struct nlist* np;
    for (np = hashtab[hash(s)]; np != NULL; np = np->next)
        if (strcmp(s, np->name) == 0)
            return np; /* found */
    return NULL; /* not found */
}

struct nlist* install(char* name, char* defn) {
    struct nlist* np;
    unsigned hashval;
    if ((np = lookup(name)) == NULL) { /* not found */
        np = (struct nlist*)malloc(sizeof(*np));
        if (np == NULL || (np->name = _strdup(name)) == NULL)
            return NULL;
        hashval = hash(name);
        np->next = hashtab[hashval];
        hashtab[hashval] = np;
    }
    else /* already there */
        free((void*)np->defn); /*free previous defn */
    if ((np->defn = _strdup(defn)) == NULL)
        return NULL;
    return np;
}

int __init() {
    puts("INIT");

    unsigned i;

    for (i = 0; i < HASHSIZE; i++) {
        hashtab[i] = NULL;
    }

    return 0;
}

void __cleanup() {
    puts("CLEANUP");

    unsigned i;
    struct nlist* np;
    struct nlist* next;

    for (i = 0; i < HASHSIZE; i++) {
        for (np = hashtab[i]; np != NULL; np = next) {
            next = np->next;
            free(np->defn);
            free(np->name);
            free(np);
        }
        hashtab[i] = NULL;
    }
}

int main() {
    unsigned i;

    for (i = 0; i < 3; i++) {
        __init();

        char buf[10];
        char buf2[10];
        unsigned j;
        for (j = 0; j < 25000; j++) {
            sprintf(buf, "N%d", j);
            sprintf(buf2, "V%d", j);
            install(buf, buf2);
        }

        __cleanup();
    }

    getchar();

    return 0;
}

Программа работает по принципу ВКЛ/ВЫКЛ. В момент запуска вызывается __init, в момент остановки __cleanup, в котором и должна производится очистка словаря. (__init и __cleanup не из книги)

В программе используется цикл, чтобы cымитиpoвaть переключение состояния программы.

Запустив код в MS Visual Studio, можно наблюдать, что при вызове __cleanup память освобождается лишь частично.

введите сюда описание изображения

Подскажите, пожалуйста, в какую сторону копать.


Ответы (0 шт):