c++hashtableaccess-violationbucketread-access

C++ HashTable Read access violation


I am building a HashTable in C++ which takes a name of a person as the key and stores his/her favorite drink, the hashtable is defined as below:

class HashTable {
private:
    static const int m_tableSize = 10;

    struct item {
        std::string name;
        std::string drink;
        item* next;
    };

    item* Table[m_tableSize];

I am using the constructor to fill every bucket in the hashtable as "empty":

HashTable::HashTable()
{
    for (int i = 0; i < m_tableSize; i++)
    {
        Table[i] = new item;
        Table[i]->name = "empty";
        Table[i]->drink = "empty";
        Table[i]->next = NULL;
    }
}

This code as it is works but, here's the question:

As far as I know, Table[i] = new item; is supposed to allocate each first item of the bucket in the heap instead of allocating in the stack, but if I try to supress this line, in other words, if I want the first item of each bucket to be allocated in the stack, the compiler throws a read access violation exception, why?

I don't necessarily want the first item of each bucket to be allocated in the stack, but I don't understand the compilers behavior in this case. I know it may be a little bit basic, but can some help?


Solution

  • I don't think the compiler is throwing that exception, but your code is provoking a read access violation exception at runtime.

    The why is because if you don't initialize Table[i] to a memory place under your program can write or read, when you call Table[i] it is pointing to some random memory address your program doesn't have access to. And thus provoking the given error.

    That said, Table is not a good name, capitalized aren't used for member variables but for custom types.

    Also take into account that you should free all the allocated memory in the destructor, a better option would be that the table is not an array of pointers to item, but an array of item. In that case, you don't need the new item and also don't need to free that memory in the destructor.

    In fact, since the hast table is supposed to be big, you should store it in dynamic memory, all the table, not just the items. I would change your code into something like this:

    class HashTable {
    private:
        static const int m_tableSize = 10;
    
        struct item {
            std::string name;
            std::string drink;
            item* next;
        };
    
        item* Table;
    ...
    public:
        HashTable() ;
        ~HashTable() ; 
    
    
    HashTable::HashTable()
    {
        Table = new item[m_tableSize]; //allocate dynamic memory for table
        for (int i = 0; i < m_tableSize; i++)
        {
            Table[i].name = "empty";
            Table[i].drink = "empty";
            Table[i].next = nullptr; //nullptr is preferred over NULL
        }
    }
    
    HashTable::~HashTable(){
       delete[] Table;
    }