Search code examples
c++hashchaining

Segmentation fault when passing array of pointers to function


I am currently working on a homeworking question and I have been trying to figure out why I keep getting a segmentation fault (core dump). I have narrowed it down to accessing an array within a function. The goal of the program is to store words from a book in a separate chaining hash table. And we can't use STL.

The array in question (Table size is 30000):

Node* hashTable = new Node[TABLE_SIZE];

The Node:

struct Node {
  unsigned int hash = 0;
  string word;
  int count;
  Node* next;
};

the function prototype that I am using:

int insert(unsigned int hash, string word, Node* table[]);

How I am calling the function:

int result = insert(hashIndex, word, &hashTable);

The function itself (yes I know its not pretty):

int insert(unsigned int hash, string word, Node* table[])
{
  unsigned int hashIndex = hash;

  Node* newNode;
  newNode->hash = hashIndex;
  newNode->count = 1;
  newNode->word = word;
  newNode->next = nullptr;

  if(table[hashIndex % TABLE_SIZE] == nullptr) {
    table[hashIndex % TABLE_SIZE] = newNode;
    return 0;
  }
  else {
    if(table[hashIndex % TABLE_SIZE]->hash == hash) {
      table[hashIndex % TABLE_SIZE]->count++;
      return 2;
    }

    Node* indexPtr = table[hashIndex % TABLE_SIZE]->next;
    while(indexPtr) {
      if(indexPtr->hash == hash) {
        indexPtr->count++;
        return 2;
      }
      indexPtr = indexPtr->next;
    }

    indexPtr->next = newNode;
  }

  return 1;
}

Whenever I try to access anything within hashTable I get a segmentation fault. Any help and criticism would be appreciated.

MINIMUM REPRODUCIBLE EXAMPLE:

#include <iostream>
#include <cctype>
using namespace std;

struct Node {
  unsigned int hash = 0;
  string word;
  int count;
  Node* next;
};

const string FILENAME = "C:/Users/Matthew/CLionProjects/p5/ulyss12.txt";
const int TABLE_SIZE = 30011;

string processWord(string word);
string removePunctuation(string word);
unsigned int hashFunc(string value);
int insert(unsigned int hash, string word, Node* table[]);
void displayHash(Node* table[]);

int main()
{
  Node* hashTable = new Node[TABLE_SIZE];
  string word = "HelloWorld";
  unsigned int hash = hashFunc(word);
  insert(hash, word, &hashTable);

  return 0;
}

string processWord(string word)
{
  if(word.length() >= 5) {
    word = removePunctuation(word);
  }
  else {
    return "";
  }

  return word;
}

string removePunctuation(string word)
{
  int i = 0;
  while(ispunct(word[i])) {
    word.erase(i, 1);
    i++;
  }

  i = word.length()-1;
  while(ispunct(word[i])) {
    word.erase(i, 1);
    i--;
  }

  return word;
}

int insert(unsigned int hash, string word, Node* table[])
{
  unsigned int hashIndex = hash;

  Node* newNode = new Node();
  newNode->hash = hashIndex;
  newNode->count = 1;
  newNode->word = word;
  newNode->next = nullptr;

  if(table[hashIndex % TABLE_SIZE] == nullptr) {
    table[hashIndex % TABLE_SIZE] = newNode;
    return 0;
  }
  else {
    if(table[hashIndex % TABLE_SIZE]->hash == hash) {
      table[hashIndex % TABLE_SIZE]->count++;
      return 2;
    }

    Node* indexPtr = table[hashIndex % TABLE_SIZE]->next;
    while(indexPtr) {
      if(indexPtr->hash == hash) {
        indexPtr->count++;
        return 2;
      }
      indexPtr = indexPtr->next;
    }

    indexPtr->next = newNode;
  }

  return 1;
}

unsigned int hashFunc(string value)
{
  const char* str = value.c_str();
  int length = value.length();

  unsigned int hash = 5381;
  int i    = 0;

  for (i = 0; i < length; ++str, ++i)
  {
    hash = ((hash << 5) + hash) + (*str);
  }

  return hash;
}

Solution

  • Thanks to both @AlanBirtles, @user4581301, and @tadman for the answers that they provided. It turns out that I had not initialized the nodes within the array to anything, so a simple for loop going through the hashTable array and setting everything to nullptr, along with the suggestions from the aforementioned users fixed the problem I was having.

    SOLUTION

      Node** hashTable = new Node*[TABLE_SIZE]{};
    

    Credit it @Eljay for the suggestion to use the curly brackets instead of a for loop.

    If there is any further issues that any of you have noticed. Please comment. Or something.