0

私が取り組んでいるハッシュ辞書では、GDB によると、配列のサイズが 500 から 1000 に一度変更されています。追加しようとしてクラッシュする配列インデックスは 799 であるため、範囲外ではありません...理由がわかりません特にそのような一見無害な回線で、セグフォルトが発生します。関連するコードは次のとおりです。

int main(int argc, char **argv)
{
FILE *src = fopen(argv[1], "r");
int algnum = 1;
char input[40];
struct HT *table = create();


if (argc == 3)
{
    if (strcmp(argv[2], "0") == 0)
    {
        algnum = 0; 
    }
    else if (strcmp(argv[2], "1") == 0)
    {
        algnum = 1;
    }
}

while(fgets(input, 40, src) != 0)
{
    int i = 0;
    while(input[i] != '\0')
    {
        i++;
    }

    struct word *wrd = malloc(sizeof(struct word));
    wrd->letters = input;
    wrd->length = i;
    if (algnum = 0)
    {
        add(table, wrd, &alg0);
    }
    else if (algnum = 1)
    {
        add(table, wrd, &alg1);
    }
}
}

次に、インクルードファイルで...

struct HT* create() 
{
struct HT* table = malloc(sizeof(struct HT));
table->entries = 0;
table->num_buckets = 500;
table->largest_bucket = 0;
table->occupied_buckets = 0;
table->buckets = malloc(500 * sizeof(struct bucket*));
int i;  
for (i = 0; i<500; i++)
{
    table->buckets[i] = malloc(sizeof(struct bucket));
    table->buckets[i]->num_items = 0;
}
return table;   
}

struct HT* resize(struct HT* table, int(*alg)(struct word *wrd)) 
{
struct HT* table_new = malloc(sizeof(struct HT));
int new_size = 2*table->num_buckets;
table_new->buckets = malloc(new_size*sizeof(struct bucket*));
int i;  
for (i = 0; i < new_size; i++)
{
    table->buckets[i] = malloc(sizeof(struct bucket));
    table->buckets[i]->num_items = 0;
}
table_new->num_buckets = new_size;
table_new->occupied_buckets = 0;
table_new->entries = 0;
table_new->largest_bucket = 0;

struct word* wrd_temp = malloc(sizeof(struct word));
struct item* item_temp = malloc(sizeof(struct item));
for (i = 0; i<table->num_buckets; i++)
{
    item_temp = table->buckets[i]->head;
    while(item_temp != 0)
    {
        wrd_temp = item_temp->wrd;
        add(table_new, wrd_temp, alg);
        item_temp = item_temp->next;
    }
}
quit(table);
return table_new;
}

void add(struct HT* table, struct word *wrd, int(*alg)(struct word *wrd)) 
{
if ((double)table->entries / (double)table->num_buckets > .75)
{
    table = resize(table, alg);
}   
sort(wrd);
int code = alg(wrd);
code = code % table->num_buckets;
struct item* item_temp = malloc(sizeof(struct item));
struct item* item_add = malloc(sizeof(struct item));
item_add->wrd = wrd;
if (table->buckets[code]->head == 0)
{
    table->buckets[code]->head = item_add;
    table->occupied_buckets++;
}
else
{
    item_temp = table->buckets[code]->head;
    while (item_temp->next != 0) {
        item_temp = item_temp->next;
    }
    item_temp->next = item_add;
}
table->buckets[code]->num_items++;
table->entries++;
if (table->buckets[code]->num_items > table->largest_bucket)
{
    table->largest_bucket = table->buckets[code]->num_items;
}
}

編集:クラッシュしている行は次のとおりです。

プログラム受信信号 SIGSEGV、セグメンテーション違反。0x0000000000400cbd in add (table=0x613cc0, wrd=0x613ca0, alg=0x400942) at ht.c:118 118 if (table->buckets[code]->head == 0)

要求された情報:

(gdb) print table->buckets[799] $2 = (構造体バケット *) 0x0

4

1 に答える 1

3

問題はresize、完全に新しいHT構造を作成することです。しかし、addあなたはこれをコールチェーンに戻さないので、mainあなたはまだ古い HT構造を持っています。

余分な補足として、あなたはfree何もしないので、多くのメモリリークが発生します.


で、main新しいテーブルを作成します。このテーブルを 1 と呼びましょう。後でいっぱいになったら、新しいテーブルを作成します。これを 2 と呼びましょう。この新しいテーブルは によって返されresize、 で使用されaddます。しかしadd、関数が返されたとき、mainまだテーブル 1 へのポインタがあります。

add次に が呼び出されると、この関数はテーブル 1 を渡しますが、これmainは小さすぎるためresizeが呼び出され、でローカルにのみ使用される別のaddテーブル 3 が作成されます。などなど…。

于 2013-04-08T14:01:54.457 に答える