ハッシュテーブルを使用して単語の辞書を実装しようとしているので、グローバルにする必要があり、ヘッダーファイルの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
をグローバルに使用する方法が間違っていると思うので、誰かがそれをグローバルに保ち、このエラーを回避する他の方法を提案できますか?
更新されたコードでは、初期化されていないポインタを使用します。
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;
}
dictionary
に割り当てるヒープ割り当ては、返されたバイトを初期化しないmalloc
を使用します。したがって、投稿したコードのdictionary
は、初期化されていないポインタの配列になります。おそらく、valgrindがエラーであることがわかっている何らかの方法でこれらのポインターを使用し続けます。
これを修正する簡単な方法は、calloc
の代わりにmalloc
を使用することです。これは、返されるバイトをゼロにするためです。または、memset
を使用して、自分でバイトをゼロにします。