web-dev-qa-db-ja.com

初期化されていない値がヒープ割り当てによって作成されました

ハッシュテーブルを使用して単語の辞書を実装しようとしているので、グローバルにする必要があり、ヘッダーファイルの1つで宣言します

extern node** dictionary;

ノードはどこにありますか

typedef struct node
{
    char* Word;
    struct node* next;
} node;

次に、関数が定義されている別のファイルに、辞書宣言を含むヘッダーを含め、上部に追加します

node** dictionary;

次に、実際に辞書をロードする関数で、最初にリンクリストにメモリを割り当ててハッシュテーブルを作成します

bool load(const char* dict_file)
{
    dictionary = malloc(sizeof(node*) * LISTS);

    FILE* dict = fopen(dict_file, "r");

    if(dict == NULL)
        return false;

    char buffer[MAX_LEN + 2];

    size_dict = 0;

    while(fgets(buffer, MAX_LEN + 2, dict) != NULL)
    {
        node* new_node = malloc(sizeof(node));

        int len = strlen(buffer);

        new_node->Word = malloc(sizeof(char) * (len));

        //avoid \n
        for(int i = 0; i < len - 1; i++)
            new_node->Word[i] = buffer[i];

        new_node->Word[len - 1] = '\0';

        new_node->next = NULL;

        int index = hash(buffer);

        new_node->next = dictionary[index];

        dictionary[index] = new_node;

        size_dict++;
    }

    if (ferror(dict))
    {
        fclose(dict);
        return false;
    }

    fclose(dict);
    return true;
}

したがって、プログラムは正常に動作し、文字列とノードに割り当てられたすべてのメモリを解放し、valgrind(メモリリークを検出するデバッガー)を実行すると、メモリリークは発生しないと表示されますが、エラーがあると表示されます 初期化されていない値は、ヒープ割り当てによって作成されました そして、上記で記述したロード関数の正確な最初の行にdictionaryのメモリを割り当てている正確な行にリダイレクトします。
何が間違っているのですか? dictionaryをグローバルに使用する方法が間違っていると思うので、誰かがそれをグローバルに保ち、このエラーを回避する他の方法を提案できますか?

5
Core_dumped

更新されたコードでは、初期化されていないポインタを使用します。

dictionary = malloc(sizeof(node*) * LISTS);

// .... code that does not change dictionary[i] for any i

new_node->next = dictionary[index];   // use uninitialized pointer

人々がすでに書いたように、これは、このループに入る前にすべてのポインターをNULLに事前設定した場合にのみ機能します。

dictionary = malloc(sizeof(node*) * LISTS);
if ( !dictionary ) {
    return false;
}

for (size_t i = 0; i < LISTS; ++i) {
    dictionary[i] = NULL;
}
7
M.M

dictionaryに割り当てるヒープ割り当ては、返されたバイトを初期化しないmallocを使用します。したがって、投稿したコードのdictionaryは、初期化されていないポインタの配列になります。おそらく、valgrindがエラーであることがわかっている何らかの方法でこれらのポインターを使用し続けます。

これを修正する簡単な方法は、callocの代わりにmallocを使用することです。これは、返されるバイトをゼロにするためです。または、memsetを使用して、自分でバイトをゼロにします。

5
John Zwinck