I'm just getting back into coding. It's been a few years. I can not figure out why this is throwing a nullptr access violation. I've condensed it into a single line of code. The violation is thrown when I try to set my second entry (newNode's pLast pointer) to head.
I'm trying to create a doubly linked list with a bubble sort based off of searches performed (aka countVar). Any help would be great.
#include <iostream>
#include <stdlib.h>
using namespace std;
//build class that has a private function to inc count.
class LinkedListCount {
private:
struct CountNode {
int data;
int countVar; //Make the variable "countVar" private to protect integrity.
CountNode* pNext = NULL;
CountNode* pLast = NULL; //Needed for bubbling back through list.
};
//Keep track of head
CountNode* head;
CountNode* current;
CountNode* temp;
public:
//Constructor Function (Set default values for head, current, and temp)
LinkedListCount() {
head = NULL;
current = NULL;
temp = NULL;
}
void AddNode(int dataIn) { //Addnode Function
//Create and populate list.
CountNode* newNode = new CountNode;
newNode->pNext = NULL;
newNode->pLast = NULL;
newNode->data = dataIn;
temp = head;
newNode->countVar = 0;
if (temp != NULL) { //We already have data entery.
if (temp->pNext == NULL) {
newNode = temp->pNext;
newNode->pLast = head; //****THIS IS WHERE ACCESS VIOLATION OCCURES
}
//Set variables with the understanding that the head is the only data point.
else {
current = temp->pNext; //Set it equal to head.
}
while (current->pNext != NULL) {//This could be eliminated with keeping track of a tail.
current = current->pNext; //Attach this to the end of the list.
}
current->pNext = newNode; //And newMode->pNext = to Null so next time I add data I'll get to the end of the list.
newNode->pLast = current;
}
else if (head == NULL) {
head = newNode;
}
}
};
void addNodes(LinkedListCount &DataList) { //Populates list.
for (int i = 0; i < 20; i++) {
DataList.AddNode(i);
}
}
int main(void)
{
addNodes(DataList);
}
if (temp->pNext == NULL) { // temp->pNext is NULL
newNode = temp->pNext; // newNode is now NULL too
newNode->pLast = head; // attempt to use pLast of NULL
}
I've put comments in your code to see why you have the access violation.
Related
I have been having troubles adding a new node at the end of a singly linked-list.
When I print the list out, I don't seem to be able to access the last node.
if (head == nullptr)
{
head = newNode;
}
else
{
record* current = head;
while (current->next != nullptr)
{
current = current->next;
}
current->next = newNode;
}
//Writing data to record.
newNode->name = name;
newNode->highscore = highscore;
newNode->initials = initials;
newNode->plays = plays;
newNode->revenue = revenue;
record* test = head;
while (test->next != nullptr)
{
cout << test->name << endl;
test = test->next;
}
You need to add nullptr after adding a new node to the list. Also, you should print the list till you reach nullptr
if (head == nullptr)
{
head = newNode;
}
else
{
record* current = head;
while (current->next != nullptr)
{
current = current->next;
}
current->next = newNode;
newNode->next = nullptr;
}
//Writing data to record.
newNode->name = name;
newNode->highscore = highscore;
newNode->initials = initials;
newNode->plays = plays;
newNode->revenue = revenue;
record* test = head;
while (test != nullptr)
{
cout << test->name << endl;
test = test->next;
}
While the other answer is good and necessary, I think it can be handled in a simpler manner. Here's an example Node.
struct Node {
int data;
Node* next = nullptr;
Node(int val) : data(val) {}
}
By default-initializing the pointer to nullptr, you don't have to constantly worry about it throughout your list class implementation. Every declared Node will automatically set the pointer to nullptr for you.
I am implementing a link list with cpp,what is wrong with the following code?
Every time i step into the function---AddToTail, the "list" can't get correct value. It changes it value to the new constructed node.
#include <iostream>
using namespace std;
struct Node
{
int value;
Node * next;
};
void AddToTail(Node* &list, int value)
{
Node newnode;
newnode.value = value;
newnode.next = NULL;
if (list == NULL)
list = &newnode;
else
{
Node * list1 = list;
while (list1->next != NULL)
{
list1 = list1->next;
}
list1->next = &newnode;
int a = 1;
}
}
int main()
{
Node *list=NULL;
AddToTail(list, 1);
AddToTail(list, 2);
AddToTail(list, 3);
while (list->next != NULL)
{
cout << list->value << endl;
list = list->next;
}
system("pause");
}
void AddToTail(Node* &list, int value)
{
Node newnode;
// Set up fields of newnode.
// Store address of newnode into some other data structure.
}
This is your issue. You are creating a node on the stack and this node will go out of scope at the end of the function. The reason it seems to be interfering with later node creations is because re-entering the function will almost certainly create newnode at exactly the same address as in the previous call.
If you want objects to survive function scope, you're going to need to allocate them dynamically, something like:
void AddToTail (Node *&list, int value) {
Node *newnode = new Node(); // create on heap.
newnode->value = value; // set up node.
newnode->next = nullptr;
if (list == nullptr) { // list empty,
list = newnode; // just create.
return;
}
Node *lastNode = list; // find last item.
while (lastNode->next != nullptr)
lastNode = lastNode->next;
lastNode->next = newnode; // append to that.
}
I'm trying to create a linked list, but I have a problem about memory access. I debug the code, see where it gives error, but cannot solve it. With using 'Add watch', can see the next has unable to read memory error.
struct Node
{
string Name;
Node* next;
};
struct LinkedList
{
Node* head = NULL;
bool isX = true;
};
LinkedList* initX(string Arr)
{
LinkedList* link = new LinkedList;
for (int i = 0; i < 15; i++)
{
Node* temp = new Node;
temp->Name = Arr[i];
Node* ptr = new Node;
ptr = link->head;
if (link->head != NULL)
{
while (ptr->next)
{
ptr = ptr->next;
}
ptr->next = temp;
temp->next = NULL;
}
else
link->head = temp;
}
return link;
}
Unhandled exception at 0x008E8AF7 in ...exe: 0xC0000005: Access violation reading location 0xCDCDCDE9.
How can I solve it?
After you set link->head to temp in the else part of your if statement, you don't set temp->next to NULL, thus making any use of temp->next as if it had a value in undefined behavior. Add this to your else part:
else {
link->head = temp;
temp->next = NULL; // or nullptr
}
It would actually be better if you moved both temp->next = NULL, made them into one, and put it as the last statement in the for loop. That why you don't have to do the same thing for both conditions.
I am working on unsorted linked list check full currently, below is my specification and implementation.
Specification:
#ifndef UNSORTEDLIST_H
#define UNSORTEDLIST_H
#include <iostream>
using namespace std;
struct Node {
float element;
Node* next;
};
class UnsortedList
{
public:
UnsortedList();
bool IsEmpty();
bool IsFull();
void ResetList();
void MakeEmpty();
int LengthIs();
bool IsInTheList(float item);
void InsertItem(float item);
void DeleteItem(float item);
float GetNextItem();
private:
Node* data;
Node* currentPos;
int length;
};
#endif
And implemetation:
UnsortedList::UnsortedList()
{
length = 0;
data = NULL;
currentPos = NULL;
}
bool UnsortedList:: IsEmpty(){
if(length == 0)
{
return true;
}
else
{
return false;
}
}
bool UnsortedList::IsFull(){
Node* ptr = new Node();
if(ptr == NULL)
return true;
else
{
delete ptr;
return false;
}
}
void UnsortedList::ResetList(){
currentPos = NULL;
}
void UnsortedList::MakeEmpty()
{
Node* tempPtr = new Node();
while(data != NULL)
{
tempPtr = data;
data = data->next;
delete tempPtr;
}
length = 0;
}
int UnsortedList::LengthIs(){
return length;
}
bool UnsortedList:: IsInTheList(float item){
Node* location = new Node();
location = data;
bool found = false;
while(location != NULL && !found)
{
if(item == location->element)
found = true;
else
location = location->next;
}
return found;
}
void UnsortedList:: InsertItem(float item){
Node* location = new Node();
location->element = item;
location->next=data;
data = location;
length++;
}
void UnsortedList:: DeleteItem(float item){
Node* location = data;
Node* tempPtr;
if(item == data->element){
tempPtr = location;
data = data->next;
}
else{
while(!(item == (location->next) ->element) )
location = location->next;
tempPtr = location->next;
location->next = (location->next)->next;
}
delete tempPtr;
length--;
}
float UnsortedList::GetNextItem(){
if(currentPos == NULL)
currentPos = data;
else
currentPos = currentPos->next;
return currentPos->element;
}
1.In the constructor, why don't assign currentPos as null?
2.In the IsInTheList function, Why points to pointer "next" ? Isn't next is a null pointer since it has been declared in struct as Node* next?
The pointer value is not set to NULL value by default, you should set to to null explicitly. Also instead of using NULL, choose using nullptr.
This code is rather incomplete, so it is difficult to answer your questions.
This does not contain the code to insert an item in the list, which is where I would expect both the next and currentPos pointers to be set. However, that's based on a number of assumptions.
However, I don't see where next is used in the "check full function" at all, so that question is a bit confusing.
I'll also point out that this code has a glaring memory leak. The first line in IsInTheList allocates memory for a new Node, which is immediately lost with location = data.
Pointers (like any other basic type) need to be initialized before use. A value of NULL is still a value.
The code you provided seems to be very incomplete. Is data supposed to be the head of your list? I am not sure how you define "fullness". If you want to test if the list is empty, you can see if your "head" of the list is null:
bool UnsortedList::IsEmpty() {
if (data == NULL) {return true;} // if there is no first element, empty
else {return false;} // if there is ANY element, not empty
}
Or more compactly:
bool UnsortedList::Empty() {
return (data == NULL);
}
When a node is added to a linked list, we usually add the node as a whole and modify the element that came before it. For example, we might create a new node and add it using code like the following:
// implementation file
void UnsortedList::InsertItem(const float& item) {
if (data == NULL) { // no elements in list, so new node becomes the head
data = new Node; // allocate memory for new node
data->element = item; // fill with requested data
data->next = NULL; // there is no element after the tail
}
else {
new_node = new Node; // allocate memory
new_node->element = item // set data
new_node->next = NULL; // new end of the list, so it points to nothing
tail->next = new_node; // have the OLD end node point to the NEW end
tail = new_node; // have the tail member variable move up
}
}
// driver file
int main() {
UnsortedList my_list;
float pie = 3.14159;
my_list.AddNode(pie);
return 0;
}
Please note that I made use of a Node* member variable called tail. It is a good idea to keep track of both where the list begins and ends.
In your IsFull function, it will always return false since it can always create a new Node*. Except perhaps if you run out of memory, which is probably more problematic.
Your functions are rather confusing and your pointer work leaves many memory leaks. You might want to review the STL list object design here.
I'm trying to incorporate push/pop into a linked list and I can't seem to get it to work. When I run my test function, I set my linked list to zero and I try to push on values but the list keeps getting returned with no values in it. Could anyone possibly tell me what I'm doing wrong?
if (top == NULL){
current = top;
current->next = NULL; //NULL->next : will cause segfault
}
if top is NULL, you set current = top [which is NULL], and then you access current->next, which will cause a segfault, you are trying to access NULL..
EDIT: follow up to comments:
your if statement seems redundant, you should probably only need to set: current->next = head; and head = current; [in addition to the current allocation]
Instead of
if (top == NULL){
current = top;
current->next = NULL;
}
you want
if (top == NULL){
top = current;
current->next = NULL;
}
And of course, after this, you have to make sure that you actually set head to top again.
Now that you've made this change, it should be clear that both cases do the same thing -- so no case distinction is actually necessary. So the function can be simplified to
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
current->next = head;
head = current;
}
The top variable is local variable for push(...) function. You can use head instead, and I'd rather modify the if statement.
I think that function should look like this:
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
if (head != NULL){
current->next = head;
head = current;
}
else{
head = current;
current->next = NULL; // if you haven't done it in LinkNode constructor
}
}
can you please specify the attributes of the linked list class ? [ is there slightly chance you are doing something wrong]
Instead of you , I'd do :
void push(Data * newPushData){
if (head == NULL)
head->data = newPushData
tail = head ;
else // regular situation
{
Node * node = new Node() ;
tail->next = node;
node->data = newPushData;
node->next = NULL ;
tail = node ;
}
}
In a linked list you have got to maintain the head pointer point on the head of the list , maintain that the tail pointer is point on the tail of the list ,
You must take care of the 2 cases of enlarging the list.
the best way for learning is to illustrate an insertion on a blank linked list.
Take care
S
void push(Data * newPushData)
{
if( head != NULL )
{
LinkNode current = new LinkNode(newPushData);
current->next = head;
head = current;
}
else
{
head = new LinkNode(newPushData);
}
}
Try this code...
void push(data * newpushdata){
if(head !=null){
linkednode current = new linkednode(newpushdata);
current->next = head;
head = current;
}
else {
head = new linkednode(newpushdata);
}
}
that is my working solution for a Stack containing int elements, but maybe it's better to create a void pushStack using Stack **S instead of Stack *S.
in pop(Stack **S) i created a sentinel, so if the stack is empty -1 is returned.:
typedef struct StackT {
int val;
struct StackT *next;
} Stack;
int isStackEmpty (Stack *S) {
if (S == NULL)
return 1;
else
return 0;
}
int *pop(Stack **S) {
Stack *tmp = *S;
int i = -1;
if (isStackEmpty(tmp) == 0) {
i = tmp->val;
*S = tmp->next;
}
return i;
}
Stack *pushStack (Stack *S, int x) {
Stack *node = (Stack *) malloc (sizeof (Stack));
node->val = x;
node->next = S;
return node;
}
you can call pop and stack easly:
Stack *S = NULL;
int x = somevalue;
int y;
S = pushStack(S, x);
y = pop(&S);