0

I have been working on the problem set speller for the last days and so far this is what I have. Unfortunately, it does not compile and I am a bit lost. I would be really grateful if somebody can help me out and tell me, what I am doing wrong.

// Implements a dictionary's functionality    
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "dictionary.h"
#define HASHTABLE_SIZE 65536
// A struct for a node
typedef struct node
{
    // Length is up to 45 + 1 for the Null
    char word[LENGTH + 1];
    // A pointer to the next node
    struct node *next;
}
node;
node *hashtable[HASHTABLE_SIZE];
node *head = NULL;

// Hashes words
// Thanks to the husband of reddit user delipity for providing the function
// https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/
int hash_it(char *word)
{
    unsigned int hash = 0;
    for (int i = 0, n = strlen(word); i < n; i++)
    {
        hash = (hash << 2) ^ word[i];
    }
    return hash % HASHTABLE_SIZE;
}

// A global var counter to keep track of all words in the dictionary
int counter = 0;
// A global var for the check function
int hashIndexForWord;
// Returns true if word is in dictionary else false
bool check(const char *word)
{
    // Making a new variable with the capacity to store the word + 1 for the \0
    char copyWord[strlen(word) + 1];
    strcpy(copyWord, word);
    // A pointer to the beginning of a node
    node *cursor = hashtable[hash_it(copyWord)];
    while (cursor != NULL)
    {
        // Checks if the word is in the dictionary
        if (strcasecmp(cursor -> word, copyWord) == 0)
        {
            return true;
        }
        else
        {
            // Move the cursor to the next node
            cursor = cursor -> next;
        }
    }
    return false;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // Load up a file and open it for reading
    FILE *file;
    file = fopen(dictionary, "r");
    char word[LENGTH + 1];
    // Making each of buckets of the table NULL
    for (int i = 0; i < HASHTABLE_SIZE; i++)
    {
        hashtable[i] = NULL;
    }
    int hashIndex;
    // Reading through the dictionary file, looking for a string
    // then putting it in a variable called word, until the EOF is reached
    while (fscanf(file, "%s", word) != EOF)
    {
        // Allocating a memory for a new node of size for a node
        node *new_node = malloc(sizeof(node));
        //node *head = malloc(sizeof(node));
        // Checking if malloc succeeded
        if (new_node == NULL)
        {
            // If it does return null, unload the dictionary and return false
            unload();
            return false;
        }
        // If it succeeds copy the word into the node
        strcpy(new_node->word, word);
        // Hashing the word and getting the index
        hashIndex = hash_it(word);
        // Pointing to the first element of the table
        new_node -> next = head;
        // Assigning the head to be the new element
        head = new_node;
        // Hashing the word and inserting a word to that place
        hashtable[hashIndex] = new_node;
        counter++;
    }
    // After the dictionary is loaded, close the file and return true
    fclose(file);
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    // TODO
    return counter;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    // Make a cursor pointing to the head
    node *cursor = head;
    while (cursor != NULL)
    {
        // A temporary node pointing to cursor
        node *temp = cursor;
        // Move the cursor to next
        cursor = cursor -> next;
        // Free the temp
        free(temp);
    }
    return true;

    // When to return false? 
}

In all of the functions I get a couple of undefined referenced and invalid symbol indexes that do not let the code compile:

undefined reference to `__ubsan_handle_nonnull_arg'

undefined reference to `__ubsan_handle_shift_out_of_bounds'

undefined reference to `__ubsan_handle_type_mismatch'

undefined reference to `__ubsan_handle_add_overflow'

undefined reference to `__ubsan_handle_divrem_overflow'
melpomene
  • 79,257
  • 6
  • 70
  • 127
viet
  • 11
  • 1
  • 1
    You are not compiling / linking it with the necessary files. – Eugene Sh. Sep 14 '18 at 13:50
  • How are you compiling your code? – melpomene Sep 14 '18 at 13:56
  • UBSAN stands for "The Undefined Behavior Sanitizer". It seems it is built-in to GCC. GCC inserts sanity checks in the code. In the makefile you seem to be able to turn it off with `UBSAN_SANITIZE := n`. I could not find references about the required libraries. See also https://www.kernel.org/doc/html/v4.16/dev-tools/ubsan.html or google "ubsan" – Paul Ogilvie Sep 14 '18 at 13:59
  • @melpomene It is an assignment, I do for CS50x, I use the cloud 9 ide and you were totally right I was not compiling it right, as Eugene Sh. said I was not linking it with the necessary files. Thanks. – viet Sep 14 '18 at 14:03
  • @EugeneSh. Thank you, I found my mistake – viet Sep 14 '18 at 14:04

1 Answers1

4

You didn't provide details about how you compile your code but I suspect you are missing -fsanitize=undefined in LDFLAGS.

yugr
  • 13,457
  • 3
  • 37
  • 71
  • 1
    This is probably correct, and it certainly was for me. I just solved this, finally after months of ignoring it by just disabling `ubsan`, using your hint. Using Meson, `-fsanitize=undefined` must be passed not only to `add_project_arguments()`, but **also** to `add_project_link_arguments()`. Now all the undefined references are gone! Thanks. I suspect this only coincidentally worked for some reason before. – underscore_d Oct 13 '18 at 13:22