Reputation: 43
I have a problem with the application crashing at the line of code where if(!head) is being referenced inside the function: insertNode(). head and tail are class members of type node*. It looks like, I am missing something in the way the class members: head, tail are initialized.. This is the runtime error: "Unhandled exception at 0x00245246 in SLinkedlist_array.exe: 0xC0000005: Access violation reading location 0x00000000."
slinkedlist.h:
typedef struct node
{
int value;
struct node* next;
} node;
class slinkedlist
{
public:
//ctor, dtor, insertNode(int, int), displayList()
private:
node* head, tail;
};
slinkedlist.cpp:
bool slinkedlist::insertNode(int value, int aftNodeVal)
{
int toinsertval = value;
int searchkey = aftNodeVal;
bool retval = false;
// If it's a new linked list
if(!head) // THIS IS WHERE THE APPLICATION CRASHES!
{
node* head = new node;
head->value = toinsertval;
head->next = NULL;
return true;
}
else //It's not a new list
{
while(head->next != NULL)
{
//some more code here...
}
}
return retval;
}
void slinkedlist::displayList()
{
while(!head)
{
do
{
cout << head->value << " " ;
head = head->next;
}
while(head->next != NULL);
}
//return void;
}
main.cpp:
int main()
{
slinkedlist *s1 = NULL;
s1->insertNode(4, -1);
s1->displayList();
while(1);
}`
Upvotes: 0
Views: 247
Reputation: 33952
slinkedlist *s1 = NULL;
defines a pointer to a slinkedlist
and DOES initialize it Unfortunately it initializes it to NULL, a safe parking address where (usually) no object are allowed to exist. For the vast majority of CPUs (every CPU I've ever worked on) accessing this dead zone around NULL will crash the program, making it much easier to detect bugs.
There is no need for a pointer here. If you don't need pointer, don't use one. Your life will be much easier.
int main()
{
slinkedlist s1; // default initializes
s1.insertNode(4, -1);
s1.displayList();
while(1); // rethink this. If you want to hold a program open to see the output
// while debugging, place a breakpoint in the debugger.
}
Default initializing of s1
alone will not help you because it will do the absolute minimum work to initialize its member variables, and in the case of a pointer the minimum work is to do nothing and leave head
and tail
uninitialized and pointing (sort of. tail
is NOT a pointer) to an indeterminate location. Because you aren't also asking about the compiler error you should get from assigning NULL
to tail
, the program is clearly not initializing tail
and I'll assume the slinkedlist
constructor doesn't do much.
Side note: If you have a constructor or destructor that don't do anything (and don't need to do anything) leave them out and let the compiler generate the appropriate code. Code that does not exist (and doesn't need to exist) has no bugs.
class slinkedlist
{
public:
//ctor, dtor, insertNode(int, int), displayList()
private:
node* head, tail; // the * only applies to head.
};
could be
class slinkedlist
{
public:
//ctor, dtor, insertNode(int, int), displayList()
private:
node* head = nullptr;
node* tail = nullptr;
};
if you are compiling to recent (2011 or newer) C++ Standards. You won't need a constructor, the work is done for you with the default assignments. You will still need a destructor along with a copy constructor and an assignment operator to satisfy The Rule of Three.
In older C++ Standards you need to make the constructor smarter
class slinkedlist
{
public:
slinkedlist(): head(NULL), tail(NULL)
{
}
//dtor, insertNode(int, int), displayList()
private:
node* head; // I recommend splitting the definitions up. It makes the code easier
// to read and makes it harder to make mistakes.
node* tail;
};
You will still need a destructor, a copy constructor, and an assignment operator.
Note that this also applies to node
. If you dynamically allocate a node and do not explicitly set next
to a value, you won't know where next
points, and all of the tests like
while(head->next != NULL)
will fail horribly.
Upvotes: 0
Reputation: 316
The answer is simple: you have null-pointer dereference here:
slinkedlist *s1 = NULL;
s1->insertNode(4, -1);
s1->displayList();
That's what exactly the system tells to you: "Access violation reading location 0x00000000"
Solution can be like:
slinkedlist *s1 = new slinkedlist;
s1->insertNode(4, -1);
s1->displayList();
delete s1;
Or like this (why not to use just an object on the stack?):
slinkedlist s1;
s1.insertNode(4, -1);
s1.displayList();
Or more C++ way (if you NEED a pointer):
auto s1 = make_unique<slinkedlist>(); // s1 is a std::unique_ptr<slinkedlist>
s1->insertNode(4, -1);
s1->displayList();
Upvotes: 1