【问题标题】:Segmentation fault on separate chaining hashtable单独链接哈希表上的分段错误
【发布时间】:2018-10-29 01:47:39
【问题描述】:

所以我为一个名为 Objective 的结构实现了一个带有单独链接的哈希表,这样我就可以对所述 Objectives 执行一些操作。目前我有这个:

哈希表.h:

#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/*Using separate chaining to store the obejctives*/

typedef struct Objective{
char name [8000];
unsigned long id, duration, deps [9000];
int hasDeps;
}*pObjective;

typedef struct nodehash{       /*Node of list*/
   pObjective obj;
   struct nodehash*next;
}*link;


void Init(int M);
int search(unsigned long id);
void insert(pObjective o);
void delete(unsigned long id);
link insertBegin(link h, pObjective obj);
int searchList(link h, unsigned long id);
link removeList(link h, unsigned long id);
pObjective searchObj(unsigned long id);
pObjective searchObjAux(link h, unsigned long id);



#endif

Objectives.c:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "OBJECTIVES.h"

/*Checks if all inserted dependencies already exist*/

int existDeps(unsigned long dep[9000]){
    int i, count = 0;

    for(i = 0; i < 9000; i++){
      if(search(dep[i]) != 0)
        count++;
    }
     return count;
}

/ *Adds objective with dependencies*/

void addObj(unsigned long id, char name [8000], unsigned long duration,
    unsigned long dep[9000]){
      int i;

    pObjective obj = malloc(sizeof(pObjective));
    obj->id = id;
    obj->duration = duration;
    obj->hasDeps = 1;
    strcpy(name, obj->name);

    for(i = 0; i < 9000; i++){
       obj->deps[i] = dep[i];
    }
    if(search(id) != 0)
       printf("id already exists\n");
   else if(existDeps(dep) != 0)
       printf("no such task\n");
   else
       insert(obj);

   free(obj);

   }

   /*Adds objective with no dependencies*/

   void addNoDeps(unsigned long id, char name [8000], unsigned long 
       duration){

   pObjective obj = malloc(sizeof(pObjective));
   obj->id = id;
   obj->duration = duration;
   obj->hasDeps = 1;
   strcpy(name, obj->name);

   if(search(id) != 0)
      printf("id already exists\n");
   else
     insert(obj);

   free(obj);

   }

  /*Removes objective with no dependencies*/

  void removeObj(unsigned long id){
        int res = search(id);
        pObjective obj = searchObj(id);

      if(res == 0)
         printf("no such task\n");
      else if(obj->hasDeps == 1)
         printf("task with dependencies\n");
      else
      delete(id);


      }

Objectives.h:

     #ifndef OBJECTIVES_H
     #define OBJECTIVES_H
     #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
     #include "HASHTABLE.h"

     /*Functions to work with objectives*/

    int existDeps(unsigned long dep[9000]);
    void addObj(unsigned long id, char name [8000], unsigned long duration,
    unsigned long dep[9000]);
    void addNoDeps(unsigned long id, char name [8000], unsigned long 
    duration);
    void removeObj(unsigned long id);    

    #endif

哈希表.c:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "HASHTABLE.h"

#define hash(A,B) (A%B)  /*Hash function*/

static link *heads;
static int M;

 /*Initiates hashtable with size m*/

 void Init(int m){
  int i;
  M = m;
  heads = (link*)malloc(M*sizeof(link));
  for(i = 0; i < M; i++)
    heads[i] = NULL;
  }

/*Searches objective with said id*/

int search(unsigned long id){
   int i = hash(id, M);
   return searchList(heads[i], id);
}

/*Inserts objective into hashtable*/

   void insert(pObjective o){
   int i = hash(o->id, M);
   heads[i] = insertBegin(heads[i], o);
   }

 /*Deletes objective using it's id*/

 void delete(unsigned long id){
   int i = hash(id, M);
   heads[i] = removeList(heads[i], id);
  }

   /*Returns objective with said id*/

   pObjective searchObj(unsigned long id){
    int i = hash(id, M);
    return searchObjAux(heads[i], id);
   }

   /*Inserts objective into list*/

   link insertBegin(link h, pObjective obj){

   link new = (link)malloc(sizeof(struct nodehash));
   new->obj = obj;
   new->next = h;
   return new;

   }

   /*Searches objective by id in a list*/

   int searchList(link h, unsigned long id){
     link t;
     int count = 0;
     for(t = h; t != NULL; t = t->next){
        if(t->obj->id == id)
          count++;
   }
   return count++;

   }

   /*Removes objective from list*/

   link removeList(link h, unsigned long id){
      link t, x, z;
      for(t = h; t != NULL; t = t->next){
         if(t->next->obj->id == id)
            x = t;
      }
      z = x->next;
      x->next = z->next;
      free(z);
      return h;
  }

  /*Returns objetive from said id from list*/

  pObjective searchObjAux(link h, unsigned long id){
     link t, x;
     for(t = h; t != NULL; t = t->next){
       if(t->obj->id == id)
         x = t;
     }
     return x->obj;
  }

我正在我的 main 上快速测试函数 addObj(添加一个具有依赖关系的目标)和 addNoDeps(添加一个没有依赖关系的目标):

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "OBJECTIVES.h"


int main(){
  unsigned long array [1] = {3};
  Init(11);
  addNoDeps(1, "tarefa1", 20);
  addObj(2, "tarefa2", 20, array);
  return 0;
}

但我不断收到分段错误(核心转储),我不知道为什么。我的实施错了吗?功能错了吗?我无法解决问题,有人可以帮助我吗?

【问题讨论】:

    标签: c struct segmentation-fault hashtable


    【解决方案1】:

    我现在无法运行您的代码,因此无法分析核心转储,但我相信您正在尝试访问已释放的内存。在 addNoDeps 结束时,将 pObjective 放入列表后释放它。然后,当您 addObj 之后,您搜索列表并检查以确保与其关联的链接对象不为空。具体这段代码:

        for(t = h; t != NULL; t = t->next){
        if(t->obj->id == id)
          count++;
    

    您只检查 t(链接指针)是否不为空,但由于您释放了前一个对象,因此 t->obj 指针未指向已初始化的内存。因此尝试通过 t->obj->id 访问它是在访问未初始化的内存。如果您在 addNoDeps 和 addObj 函数末尾删除 free(obj) 应该没问题。您可能还想添加检查以确保 t->obj 也不为空。通常,分段错误是由访问未初始化的内存引起的,因此在调试时检查是否在释放、双重释放和其他事情之后访问指针。在这些情况下,学习使用 GDB 也有很大帮助。

    【讨论】:

    • 非常感谢您的建议,我删除了 free(obj) 并添加了检查以查看 t->obj 是否不是 NULL 但我仍然遇到分段错误...
    • 我使用了 GDB,基本上是 addObj、addNoDeps 以及我遍历列表的所有函数(searchList、removeList、searchObjAux)不断给出 seg 错误......我的实现有问题吗哈希表?
    • 好的,你需要做的其他事情是 a。在 addObj 和 addDepObj 中的 strcpy(name, obj-&gt;name) 中,只需切换名称和 obj->name。 strcpy 是 strcpy(destination, source) 。另一件事是你给 addObj 一个大小为 1 的数组,但参数需要一个大小为 9000 的数组?我不确定你想要什么,但如果你尝试访问你给的东西,你会在那里得到另一个段错误。您可能还应该传递一个数组大小,这样该函数就不会过去。在我修复了这些东西之后,你的代码在我的机器上构建并运行良好。
    • 我从来不知道要添加的数组的大小,只知道它的最大元素数是 9000,这就是为什么,当我声明结构时,我将 deps 声明为具有 9000 个元素的数组,但它可以有 0 到 9000 个元素。在 AddObj 方法中,参数 dep 可以有 1 到 9000 个元素。我应该将 AddObj 中的结构元素 deps 和 dep 更改为指针吗?因为当我将数组大小声明为 9000 时,我永远无法将其更改回来。
    • 将 dep 更改为指针不会改变问题。如果您不知道要添加的数组的大小,您将永远无法迭代它,因为您永远不知道迭代多远。找到一些方法来跟踪大小。
    猜你喜欢
    • 2012-04-23
    • 2023-03-03
    • 2022-01-10
    • 2016-03-03
    • 2013-12-25
    • 2020-08-24
    • 1970-01-01
    • 2019-11-26
    相关资源
    最近更新 更多