Ошибка сегментации в отдельной хэш-таблице цепочек - PullRequest
0 голосов
/ 18 мая 2018

Итак, я реализовал хеш-таблицу с отдельной цепочкой для структуры под названием Objective, чтобы я мог выполнять некоторые операции над указанными Objectives.В настоящее время у меня есть это:

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 голосов
/ 18 мая 2018

Я не могу запустить ваш код прямо сейчас, поэтому не могу проанализировать дамп ядра, но я верю, что происходит то, что вы пытаетесь получить доступ к памяти, которая уже была освобождена.В конце addNoDeps вы освобождаете pObjective после помещения его в список.Затем, когда вы добавляете addObj после, вы просматриваете список и проверяете, чтобы убедиться, что объект ссылки, связанный с ним, не является нулевым.В частности, этот код:

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

Вы только проверяете, чтобы видеть, что t (указатель ссылок) не является нулевым, но, поскольку вы освободили предыдущий объект, указатель t-> obj не указывает на инициализированный memroy.Поэтому попытка доступа к нему через t-> obj-> id приводит к обращению к неинициализированной памяти.Если вы удалите free(obj) в конце функций addNoDeps и addObj, все будет в порядке.Вы также можете добавить проверки, чтобы убедиться, что t-> obj также не равно нулю.В общем, ошибки сегментации вызваны доступом к неинициализированной памяти, поэтому при отладке проверяйте доступ к указателям после освобождения, двойного освобождения и других вещей.Кроме того, обучение использованию GDB может очень помочь в этих ситуациях.

...