单独链接哈希表上的分段错误

时间:2018-05-18 15:11:14

标签: c struct segmentation-fault hashtable

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

Hashtable.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

Hashtable.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;
  }

我正在快速测试功能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;
}

但我不断得到分段错误(核心转储),我无法弄清楚原因。我的实施错了吗?功能有误吗?我无法解决问题,有人可以帮助我吗?

1 个答案:

答案 0 :(得分:1)

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

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

您只检查t(链接指针)是否为空,但由于您释放了前一个对象,因此t-&gt; obj指针不指向初始化的memroy。因此,尝试通过t-&gt; obj-&gt; id访问它是访问未初始化的内存。如果你删除addNoDeps和addObj函数末尾的free(obj),你应该没问题。您可能还想添加检查以确保t-&gt; obj也不为空。一般来说,分段错误是由访问未初始化的内存引起的,所以在调试时检查访问指针后的free,double frees等等。在这些情况下,学习使用GDB也可以提供很多帮助。