C++ unhandled exception. 0xC0000005: Access violation reading location 0xccccccd0

David Rutledge picture David Rutledge · Sep 2, 2014 · Viewed 16.8k times · Source

I have been trying to work through this for the past couple of hours by going through my call stack, and have still yet to figure out what is going on!

My Sequence Database that basically gathers the info needed from a file, then calls on my Linked List class to create a new node with the gathered info, and put that node at the end of the Linked List:

Header:

#ifndef SEQUENCE_H
#define SEQUENCE_H
#include "DNA.h"
#include "DNAList.h"

class SequenceDatabase
{
public:
    //Default Constructors
    SequenceDatabase();

    //Methods
    void importEntries(string);


private:
    DNAList list;
};

#endif

Source:

#include "SequenceDatabase.h"
#include "DNA.h"
#include "DNAList.h"
#include <fstream>

using namespace std;
SequenceDatabase::SequenceDatabase() //Default Constructor.
{
    DNA object;
    DNAList list;
}

void SequenceDatabase::importEntries(string name)
{
    DNA* item;
    ifstream file;
    file.open(name);

    if(!file.is_open())
    {
        cout << "Error opening file!" << endl;
        exit(1);
    }

    char letter;
    string label, sequence;
    int ID, length, index;
    file >> letter;

    if(letter == 'D' || letter == 'd')  
    {
        file >> label >> ID >> sequence >> length >> index;
        DNA object(label,ID,sequence,length,index);
        item = &object;
        DNAList list(item);
    }


}

My Linked List Header file:

class DNAList
{
public:
    //Constructors
    DNAList();
    DNAList(DNA* newDNA);

    //Linked List Functions
    void push_back(DNA* newDNA);
    DNA* findID(int ID);
    void obliterate(int ID);

    //DNANode struct for Linked List
    struct DNANode
    {
        DNA* data;
        DNANode* next;
        DNANode* prev;
    };


private:
    DNANode* head;
    typedef DNANode * ptr;
};

#endif

My Linked List class source file:

#include "DNAList.h"
#include "SequenceDatabase.h"
#include "DNA.h"
#include <iostream>

using namespace std;

DNAList::DNAList()
{
    head = NULL;


}

DNAList::DNAList(DNA* newDNA)
{
    cout <<"In DNA list second constructor" << endl;
        ptr cur;
    if(head == NULL)
    {
        ptr newNode = new DNANode;
        cur = newNode;
        cur -> data= newDNA;
        head = cur;
        cur -> prev = head;
        cur -> next = NULL;
    }
    else 
    {
        push_back(newDNA);
    }
}

void DNAList::push_back(DNA* newDNA)
{
    ptr cur;
    ptr last;
    cout << "Note: Adding " << newDNA -> getID() << " ..." << endl;
    ptr newNode = new DNANode;
    cur = head;
    while(cur != NULL)
    {
        last = cur;
        cur = cur -> next; //ERROR IS HAPPENING AT THIS LINE.
    }
    newNode -> data = newDNA;
    newNode -> prev = last;
    newNode -> next = NULL;
    cur = newNode;

}

Now, I am new to using classes to contain my linked lists, so I am not sure if my node struct should be in public or private memory for my Linked List class, and also if my constructors are defined the way they should be. The Node struct is basically a pointer to the actual data that is in a header file called DNA with additional pointers to the struct for my next and previous Nodes so that the data is never messed with, but just pointed to.

The error is being stuck on the line right in the middle of my push_back function in my Linked List source file. I labeled it appropriately. Please can someone share some insight on what I am doing wrong here? Thanks!

My main file:

#include <iostream>

using namespace std;

#include "sequenceDatabase.h"

int main(){ //int argc, char* argv[]){
    string commandsFileName;
    commandsFileName = "lab1-commands-short.tab"; // for initial development
    //commandsFileName = "lab1-commands.tab";
    // commandsFileName = "lab1-commands-test.tab"; // for testing & grading

    SequenceDatabase entries;
    cout << "Importing " << commandsFileName << endl;
    entries.importEntries(commandsFileName);

    return 0;
}

Answer

0x499602D2 picture 0x499602D2 · Sep 2, 2014
if (...)
{
    DNA object(label, ID, sequence, length, index);
    item = &object;
    DNAList list(item);
}

object is a locally-scoped object, meaning it is destroyed at the ending brace of the block. You're setting item to point to that local object and sending if off to the constructor of DNAList. The problem with that is if you try to access object after it has been destroyed, your program will no longer be in a valid state. This is because once your object is destroyed, the object that pointed to it will be left as a dangling pointer. Things like accessing a dangling pointer is known as Undefined Behavior.

But that's not where your UB comes from (yet). The real problem is in your DNAList constructor:

if (head == NULL)
{
    // ...
}
else
{
    push_back(newDNA);
}

head is an uninitialized pointer. Primitive objects (like int, char, char*) that are declared but not defined are uninitialized and thus have an indeterminate value. Testing objects in this state as if they had a value is also Undefined Behavior.

Note that UB can still appear to make your code work properly. But it can also do other nasty things that make no logical sense in your program.

head has the value of whatever was stored in the stack at that moment, which probably wasn't 0. So the condition fails and push_back() is invoked.

Then you do cur->next inside the while loop which dereferences an uninitialized pointer, finally causing an exception to be thrown.

That particular runtime error could be avoided by setting head to NULL inside the constructor body of DNAList and dynamically allocating object (so that it exists beyond the scope of the if statement, but there are still a few more things that are not right in your program as specified in the comments.