【问题标题】:Code Seg Faults after atleast 375 Successful Entries至少 375 次成功输入后的代码段错误
【发布时间】:2013-04-08 13:54:43
【问题描述】:

在我正在处理的哈希字典中,根据 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 在 ht.c:118 处添加(表=0x613cc0,wrd=0x613ca0,alg=0x400942) 118 if (table->buckets[code]->head == 0)

要求的信息:

(gdb) 打印表->buckets[799] $2 = (struct bucket *) 0x0

【问题讨论】:

  • 所有条目letters 成员将是相同的。你让它们 all 指向同一个数组,当你读取文件时它会被更新。
  • 分割前table->buckets[code]的值是多少?
  • 至于报错,第118行是哪一行?
  • 另外,在调整分配的内存大小时,使用realloc不是更容易吗?
  • @JoachimPileborg 我想哈希码取决于表的大小,所以调整大小后需要放入不同的存储桶。

标签: c


【解决方案1】:

问题是在resize 中你创建了一个全新的HT 结构。但是在 add 中,您不会将其传递回调用链,因此在 main 中,您仍然拥有 HT 结构。

另外补充一点,你从来没有free 任何东西,所以你有很多内存泄漏。


main 中创建一个新表。让我们将此表称为 1。稍后当它变满时,您将创建一个 new 表,我们将其称为 2。此新表由 resize 返回并在 add 中使用。但是当add 返回时,main 函数仍然有一个指向表 1 的指针。

因此,当下次调用 add 时,main 函数会传递表 1,该表太小,因此会调用 resize 并创建 另一个表 3,该表已被使用仅在本地 add。等等等等……

【讨论】:

  • 我不这么认为。当我在段错误发生时打印 table->num_buckets 我得到 1000,这意味着它已经调整大小。
  • @SwiftCore 那是因为你又调用了resize再次。在第一次之后,您实际上会在add每次 调用resize,甚至不会将新数据添加到适当的位置。
  • 但是我调用它之后,它有一个新的num_buckets,所以它应该跳过resize分支?
  • @SwiftCore 您实际上可以通过临时将大小设置为小来轻松调试它,因此它必须尽早调整大小。然后单步调试调试器中的代码,输入addresize,同时检查例如table 在不同的功能中。
  • @SwiftCore 否,因为那时使用的是来自mainold 结构指针,它没有更新或调整大小。如果你在调整大小后释放了旧结构,你会在resize 中得到另一个段错误,因为指针已经被释放了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-31
  • 2022-11-09
  • 1970-01-01
相关资源
最近更新 更多