_Right_datqa was nullptr error

Hi,
I'm doing a project in my text book about Link-List called "Pile of Books". I am trying to create a remove method that removes the first node in the list. However the code I cam up with gives me a "read access violation. _Right_data was nullptr." exception when i try to compile and run the program.
I narrowed the problem down to the line in "headPtr = headPtr->getNext();" in the remove() method, but I am not sure why this is, as I've basically used the same code in a previous assignment and it worked. Here is all my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#pragma once


template<class ItemType>
class Node
{
private:
    ItemType        item; // A data item
    Node<ItemType>* next; // Pointer to next node

public:
    Node();
    Node(const ItemType& anItem);
    Node(const ItemType& anItem, Node<ItemType>* nextNodePtr);
    void setItem(const ItemType& anItem);
    void setNext(Node<ItemType>* nextNodePtr);
    ItemType getItem() const;
    Node<ItemType>* getNext() const;
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#include "Node.h"
//#include <cstddef>

template<class ItemType>
Node<ItemType>::Node() : next(nullptr)
{
} // end default constructor

template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem) : item(anItem), next(nullptr)
{
} // end constructor

template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem, Node<ItemType>* nextNodePtr) :
    item(anItem), next(nextNodePtr)
{
} // end constructor

template<class ItemType>
void Node<ItemType>::setItem(const ItemType& anItem)
{
    item = anItem;
} // end setItem

template<class ItemType>
void Node<ItemType>::setNext(Node<ItemType>* nextNodePtr)
{
    next = nextNodePtr;
} // end setNext

template<class ItemType>
ItemType Node<ItemType>::getItem() const
{
    return item;
} // end getItem

template<class ItemType>
Node<ItemType>* Node<ItemType>::getNext() const
{
    return next;
} // end getNext 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//PileOfBooksInterface.h
#pragma once

#include <string>
#include <vector>
class PileOfBooksInterface
{
public:
	/** Adds a book to the top of the pile
	@param addBook is a string of the title of the book the client wants to add to the top of the pile
	@returns true is book is succesfuly added, and false otherwise*/
	virtual bool add(std::string addBook) = 0;

	/** Removes the top book from the pile if the pile is not empty
	@returns true is book is successfuly removed and false otherwise*/
	virtual bool remove() = 0;

	/** Removes all books from the pile */
	virtual void emptyOut() = 0;

	/** Puts all books in the pile to a vector
	@return a Vector of the pile of books */
	virtual std::vector<std::string> toVector() = 0;
};






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//PileofBooks.h
#pragma once

#include "PileofBooksInterface.h"
#include <string>
#include <vector>
//#include "Node.h"
#include "Node.cpp"
class PileOfBooks : public PileOfBooksInterface
{
private:
	Node<std::string>* headPtr; // Pointer to first node
	int itemCount;           // Current count of bag items

	// Returns either a pointer to the node containing a given entry
	// or the null pointer if the entry is not in the bag.
	//Node<std::string>* getPointerTo(const std::string& target) const;
public:
	/** Construct an empty pile of books */
	PileOfBooks();

	/** Destructure */
	~PileOfBooks();

	/** Adds a book to the top of the pile
	@param addBook is a string of the title of the book the client wants to add to the top of the pile, title must not be an empty string
	@returns true is book is succesfuly added, and false otherwise*/
	bool add(std::string addBook);

	/** Removes the top book from the pile if the pile is not empty
	@returns true is book is successfuly removed and false otherwise*/
	bool remove();

	/** Removes all books from the pile */
	void emptyOut();

	/** Puts all books in the pile to a vector
	@return a Vector of the pile of books */
	std::vector<std::string> toVector();

};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//PileofBooks.cpp
#include "PileofBooks.h"
#include <cctype>
#include <iostream>
#include <string>


PileOfBooks::PileOfBooks()
{
	headPtr = nullptr;
	itemCount = 0;
	
}

bool PileOfBooks::add(std::string addBook)
{
	Node<std::string>* nextNodePtr = new Node<std::string>();
	nextNodePtr->setItem(addBook);
	nextNodePtr->setNext(nullptr);
	if (itemCount == 0)
	{
		headPtr = nextNodePtr;
	}
	else
	{
		Node<std::string>* lastNodePtr = headPtr;
		headPtr = nextNodePtr;
		nextNodePtr->setNext(lastNodePtr);
	}
	itemCount++;
	return true;

}


bool PileOfBooks::remove()
{
	if (headPtr != nullptr)
	{
		Node<std::string>* removing = headPtr;
		headPtr = headPtr->getNext();
		removing->setNext(nullptr);
		delete removing;
		removing = nullptr;
	}
	return true;
}

void PileOfBooks::emptyOut()
{
	itemCount = 0;
}

std::vector<std::string> PileOfBooks::toVector()
{
	std::vector<std::string> allBooks;
	Node<std::string>* nexPtr = headPtr;
	for (int i = 0; i < itemCount; i++)
	{
		allBooks.push_back(nexPtr->getItem());
		nexPtr = nexPtr->getNext();
	}

	return allBooks;
}


PileOfBooks::~PileOfBooks()
{

}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//main.cpp
#include "LinkedBag.cpp"
#include "PileofBooks.h"
#include <iostream>

int main()
{
	PileOfBooks zelda;
	zelda.add("Link to the Past");
	zelda.add("Hyruel Warriors");
	zelda.add("Age of Calamity");
	zelda.remove();
	std::vector<std::string> pile = zelda.toVector();
	for (int i = 0; i < pile.size(); i++)
	{
		std::cout << pile[i] << std::endl;
	}

	return 0;
}
The crash occurs in toVector(). The problem is that you use (unnecessarily) itemCount. PileOfBooks::remove() does not decrease itemCount. Therefore you get a nullptr.

I would suggest to eliminate itemCount entirely.

To solve your current problem you can add --itemCount; somewhere between line 39 and 45 in PileOfBooks::remove().
If you are using at least a C++11 compiler, you can simply your code by using auto. eg

 
Node<std::string>* nexPtr = headPtr;


becomes:

 
auto nexPtr = headPtr;


The compiler knows the type and automatically assigns the known type. There's no need to explicitly specify the type.

THANK YOU!!!!!!
Topic archived. No new replies allowed.