0

My load() function updates a global array initialized to NULL. check() thereafter converts word to lowercase and stores it in a buffer. Most elements in the array store NULL, however sometimes a real memory address is found and the condition for the while loop, as well as the if condition succeeds and true; gets returned.

The relevant two functions are below together with global variables and arrays.

// Global variables and arrays for simple access
char buffer[LENGTH+1]; // Declares the buffer to store one line or one word in total
int wordcount = 0;
int hash_index;

node* head_array[HASHTABLE_SIZE] = {NULL}; // Stores pointer to node datatype
node* head_node;  // Will always be the most recent node, and first in the list
FILE* dict_file;


/**
 * Returns true if word is in dictionary else false.
 */
bool check(const char* word)
{
    for (int i = 0, wordlen = strlen(word); i < wordlen; i++) {
        buffer[i] = tolower(word[i]);
        buffer[i+1] = '\0';
    }

    hash_index = hash(buffer);
    head_node = head_array[hash_index];

    while (head_node != NULL) {
        if (strcmp(buffer, head_node->word))
            return true;

        head_node = head_node->next;
    }

    return false;
}

 /**
 * Loads dictionary into memory. Returns true if successful else false.
 */
bool load(const char* dictionary)
{
    // Open dictionary file, and error-check
    dict_file = fopen(dictionary, "r");
    if (dict_file == NULL)
        return false;


    while (fgets(buffer, LENGTH+1, dict_file) != NULL) {

        // Temporary reference to the current hash
        hash_index = hash(buffer);

        // Create new node and fill it's word field with the contents of buffer
        head_node = malloc(sizeof(node));
        if (head_node == NULL) {
            printf("malloc returned NULL");
            return false;
        }

        strcpy(head_node->word, buffer);

        if (head_array[hash_index] == NULL)
            head_node->next = NULL;

        else
            head_node->next = head_array[hash_index];

        head_array[hash_index] = head_node;

        wordcount++;
    }

    return true;
}

EDIT: After some messing around with gdb I see that head_array contains:

{0x0, 0x0, 0xebd750, 0x0, 0x0, 0x0, 0xebef10, 0x0, 0x0, 0x0, 0xebe510, 
  0x0, 0x0, 0x0, 0xebed10, 0x0, 0x0, 0x0, 0xebee50, 0x0, 0x0, 0x0, 0xebded0, 
  0x0, 0x0, 0x0, 0xebe890, 0x0, 0x0, 0x0, 0xebeb50, 0x0, 0x0, 0x0, 0xebe550, 
  0x0, 0x0, 0x0, 0xebe650, 0x0, 0x0, 0x0, 0xebebd0, 0x0, 0x0, 0x0, 0xebecd0, 
  0x0, 0x0, 0x0, 0xebe850, 0x0, 0x0, 0x0, 0xebed50, 0x0, 0x0, 0x0, 0xebeed0, 
  0x0, 0x0, 0x0, 0xebe110, 0x0, 0x0, 0x0, 0xebee90, 0x0, 0x0, 0x0, 0xebec10, 
  0x0, 0x0, 0x0, 0xebee10, 0x0, 0x0, 0x0, 0xebe410, 0x0, 0x0, 0x0, 0xebe1d0, 
  0x0, 0x0, 0x0, 0xebe610, 0x0, 0x0, 0x0, 0xebe010, 0xbd1a90, 0x0, 0x0, 
  0xebedd0, 0x0, 0x0, 0x0, 0xebec50, 0x0}
1

" It was initialized to NULL as soon as the load function ran, prior to being declared globally. "

That's not exactly true, nor is it the complete truth. Note the following statement inside of load():

    node* head_array[HASHTABLE_SIZE] = {0};

head_array is first globally declared at the top of the program. Then the statement above redeclares head_array inside of load, after the global declaration, along with initializing it.

This is called declaring a shadow variable. It will have local scope. The second declaration creates a new, local array that supercedes and hides the global array. The shadow array is used inside of load, where it is in scope, not the global array. As soon as the code exits load(), the shadow array will cease to exist and the global array will reassert, but since it is a pointer array and was never initialized, it will contain garbage data for node addresses.

The code needs to initialize head_array without redeclaring it. Also, it would be better to initialize node pointers to NULL, not zero, for clarity.

If this answers your question, please click the check mark to accept. Let's keep up on forum maintenance. ;-)

3
  • By changing node* head_array[HASHTABLE_SIZE] = {0}; to head_array[HASHTABLE_SIZE] = {NULL}; I am now getting an "expected expression" error at the same line, column 34 -- or just under the first bracket of "{NULL}". I encountered this error before adding node* to the statement, so that adding node* just silenced the error, right?
    – kluvin
    Sep 9 '16 at 5:57
  • wrong. it's just trading one problem for another, larger one. It may silence the error, but it's creating a shadow array. If you want to declare and initialize to NULL at the same time, you can do it at the global declaration, but you absolutely can't declare it a second time with the node* preface inside of load.
    – Cliff B
    Sep 9 '16 at 6:26
  • I have updated the code and description to better reflect the initial issue I wanted to address. Most significantly the head_array is now initialized to NULL globally
    – kluvin
    Sep 9 '16 at 12:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .