Program crashes when opening and processing input files - c++

I'm currently working on a program, and I'm running into a small issue. It's reading data from a text file, and when the numbers are in ascending order, it runs fine, but when I have numbers in a random order, it crashes. I've debugged it and traced it to this if statement, but I can't figure out what the heck I did wrong.
if(tempNode != NULL)
{
struct doublyLinkNode* temp = new doublyLinkNode;
temp->nextNode = tempNode;
temp->previousNode = tempNode->previousNode;
temp->nodeValue = noToInsert;
tempNode->previousNode->nextNode = temp;
tempNode->previousNode= temp;
list->count++;
return true;
} // end if
The list building crashes when a new number to be added precedes the current top of the list. I think the pointer is attempting to write to an invalid pointer.

Your error is to be expected. You want to insert nodes before the current one (tempNode),
and you´re using tempNode->previousNode in the code.
If tempNode happens to be the first node, what´s tempNode->previousNode? Right, NULL
(unless you have a circular list, but then you wouldn´t have this problem). That means
tempNode->previousNode->nextNode = temp; will crash.
As solution to this part, just make an if:
if(tempNode->previousNode != NULL) tempNode->previousNode->nextNode = temp;
(assuming that everything is initialized properly). Depending on how you implemented the list, you may need to change the information what the first node is, too.

Related

Why is the delete temp crashing even though the function is defined with new

I am making a modified double ended Linked List, but the head and the tail point to each other. In the insertBeforeCurrent and the insertAfterCurrent I defined the objects with new and put them into the Linked List. But when I go to use delete, the program just crashes. I have done some tests, and insertBeforeCurrent and insertAfterCurrent works, and I am able to through the Linked List and print every single element with the getPrevious and getNext. I also printed it using only insertBeforeCurrent, insertAfterCurrent and I was also able to do the same with the mixture of the two. I was able to print it with 1,2,3,and 6 elements in the Linked List. The problem I have is the debugger, everything works until I hit the delete temp; at which point it will just say.
Can't find a source file at "/build/glibc-t7JzpG/glibc-2.30/signal/../sysdeps/unix/sysv/linux/raise.c"
Locate the file or edit the source lookup path to include its location.
I know you can only use the delete function for delete the data created by the new's dynamic memory allocation, but that doesn't seem to be the case since every element of the Linked List is created by new.
So the issue with application crashing is not the Node * x = new Node(); followed by x = y;. These don't show any warnings,the application runs, and 5 or 6 people have pointed them out. Thank you by the way. My issue is specifically is the delete temp;and why is it not being deleted. I have left the code for some context.
EDIT: I have removed the insertBeforeCurrent and insertAfterCurrent code since it is not needed.
bool CircularDoublyLinkedList::remove(int original_data)
{
Node search_data = search(original_data);
Node* temp = &search_data;
Node* current_next;
Node* current_previous;
if (temp != NULL)
{
if (temp == head)
{
current_previous = temp->getPrevious();
current_next = temp->getNext();
current_previous->setNext(current_next);
current_next->setPrevious(current_previous);
head = current_next;
temp->setNext(NULL);
temp->setPrevious(NULL);
delete temp;
current = current_next;
cout << "Delete successful." << endl;
}
else if (temp == tail)
{
current_previous = temp->getPrevious();
current_next = temp->getNext();
current_next->setPrevious(current_previous);
current_previous->setNext(current_next);
tail = current_next;
temp->setNext(NULL);
temp->setPrevious(NULL);
delete temp;
current = current_next;
cout << "Delete successful." << endl;
}
else
{
current_previous = temp->getPrevious();
current_next = temp->getNext();
current_previous->setNext(current_next);
current_next->setPrevious(current_previous);
temp->setNext(NULL);
temp->setPrevious(NULL);
delete temp;
}
return true;
}
return false;
}
I know you can only use the delete function for delete the data created by the new's dynamic memory allocation,
So far so good.
but that doesn't seem to be the case since every element of the Linked List is created by new.
This is not relevant, since the temp in CircularDoublyLinkedList::remove() never points to an element of the linked list. You assign to temp the address of a local variable (search_data) and never change that. Local variables are not created by new, so (as you noted earlier), you cannot delete &search_data.
(You might have noticed this yourself had you used a debugger to step through your code while trying to delete the first element of the list. In your current code, temp == head will never be true, even though that is the branch for deleting the first element. Similarly, temp == tail will never be true, and temp != NULL will never be false.)
At a guess, your search() function should probably return a pointer to a node in the list instead of returning the node, at which point you'll no longer need the (poorly-named) temp variable.

Create a checkerboard or "Interweave" two linked-lists. IE changing the pointers of two linked lists

So I have two linked lists, each holding a color:
1.black->2.black->3.black->4.black->5.black->NULL
1.red ->2.red ->3.red ->4.red ->5.red ->NULL
I want the function to return
1.black->2.red ->3.black->4.red ->5.black->NULL
1.red ->2.black->3.red ->4.black->5.red ->NULL.
Lets name the first pointers, firstBlack and firstRed. To achieve this "checkerboard" pattern, I switch the nodes that each first is pointing to with a simple swap to the other list, advance the pointer two spots, then repeat until I'm at the end of the list.
while(firstBlack->next != NULL && firstRed->next != NULL) {
Node * temp = firstBlack->next;
firstBlack->next = firstRed->next;
firstRed->next = temp;
firstBlack = firstBlack->next->next;
firstRed = firstRed->next->next;
}
However, the function isn't doing what it's supposed to although I'm fairly certain that my logic is correct. I am also getting seg faults :(
This is a simple enough code, please use a debugger and debug the code step by step.
Also please post the entire code not just what's in the while loop.
This code should work correctly.
//Some methods to create these linked lists.
pBlackHead = CreateBlackList();
pRedHead = CreateRedList();
firstBlack = pBlackHead;
firstRed = pRedHead;
while(firstBlack->next != NULL && firstRed->next != NULL){
Node * temp = firstBlack->next;
firstBlack->next = firstRed->next;
firstRed->next = temp;
firstBlack = firstBlack->next;
firstRed = firstRed->next;}
While printing the list to check the correctness use pBlackHead , pRedHead. A debugger is not currently available on the system I am using but this should work.
You are advancing two steps without checking end conditions. Because you have an odd number of items, you dereference a null pointer.
You don't need to care which tail originated in which list to swap them
for(; left->next && right->next; left = left->next, right = right->next) {
std::swap(left->next, right->next);
}

How to remove duplicates from linked list which repeats double number of times?

I've been trying to create own linked list class on C++. My task is remove all nodes which data repeats double number of times in list and store only one node if data repeats odd number of times. I've written function removeDuplicates(), but my program crashes when i try to use the function. Implementation here:
void LinkedList::removeDuplicates(){
Node *ptr1, *ptr2, *dup, *toDel;
int counter = 1;
ptr1 = top;
while(ptr1 != NULL && ptr1->next != NULL){
ptr2 = ptr1;
while(ptr2->next != NULL){
if(ptr1->name == ptr2->next->name){
dup = ptr2->next;
ptr2->next = ptr2->next->next;
delete dup;
counter++;
} else {
ptr2 = ptr2->next;
}
}
if(counter % 2 == 0){
toDel = ptr1;
ptr1->next = ptr1->next->next;
ptr1 = ptr1->next;
delete toDel;
}else{
ptr1 = ptr1->next;
}
}
}
Firstly: Please learn to use a debugger. Knowing the exact line where it crashes and looking at the variables and pointers at runtime, and stepping through the code will save you from asking these: "I wrote some code, it's broke, fix it please." 'questions'.
If gdb is unwieldy for you, use visual studio or something.
As Some programmer dude suggested: learn how to debug your code.
Regarding your actual problem:
After your inner loop.
ptr1->next = ptr1->next->next;
is not checked if (ptr1->next == NULL). Thus accessing ptr1->next->next will result in an access violation.
While that check is in the outer while loop condition, the inner while loop may delete and unlink the object from your list.
I'm also fairly certain that you want to reset your counter somewhere in the outer loop, probably right at the start. as it is now, it doesn't count the number of occurences of any one ptr2->name
Also you should initialize variables right in the declaration, it's just good style and may avoid further hassle.
It is also a good idea to set your pointers to NULL after deleting, so you DO get a nice null pointer exception instead of it randomly 'working' or crashing.

Deleting elements from doubly bounded pointer list

I am working on a project where I create a double bounded pointer list, delete several elements, and still be able to read off the list. I have a double bounded pointer list, but am having trouble deleting elements and keeping the list double bounded. This then causes issues when trying to print the list.
Below is the IF statement I've placed in a while loop to help delete unwanted elements. I keep getting a segmentation fault (core dumped).
if ((black2 != black)||(white2 != white)) {
dump = help;
help = help ->next;
dump -> before = temp;
temp -> next = help;
help ->before = temp;
delete dump;
}//if
else { temp = help;
help = help->next;
help ->before = temp; }//else
To maintain properly the doubly linked list you should do something like :
void remove(X *elt) {
X* before = elt->before;
X* after = elt->next;
if (before != NULL) { // assuming first element points to NULL
before->next = after;
}
else {
first = after; // assuming first is a pointer to first element of list
}
if (after != NULL) { // assuming last element points to NULL
after->before = before;
}
else {
last = before; // assuming last is a pointer to last element
}
delete elt;
}
That way, you ensure that elements around current correctly point to each other dealing with special cases of removing first or last element.
But you already have a std::list template in Standard Template Library
One logical issue in your code is the line dump->before = temp.
What this does is that it sets the previous node pointer of dump to temp, as opposed to defining temp as the previous node.
The correct line should read temp = dump->before
PS: Your code is correct assuming that the node you are deleting isn't the first or last node (and you haven't padded with dummy nodes). You should introduce checks for these cases if required.

Circular Traversal of a Linked List

So I'm having some trouble with one of my functions. The program (in C++) plays a game, and there are so many players sitting at the table. Every time my play function is called, it should display to the console a player in the game. Every time it is called it should display the players in sequence. After it hits the last player it will start back at the beginning of the list/table.
void CircleList::play()
LinkedListOfPlayersNode *p=(*pFront).pNext;
if (p->pData!=NULL)
{
cout<<p->pData->getName()+" takes a turn\n";
pLastPlayer = pLastPlayer->pNext;
}
else
{
cout<<"There are no players. Please ADD a player.\n";
}
}
So lets say that that we add A, B, and C. When you use the PLAY command, C should take a turn, then B then A. As of right now with the above code, it will display that C Takes a Turn, however, it crashes right after that.
So what is wrong with my code? Is there a better way to write this?
I'm pretty sure you want that traversal to look something like this:
LinkedListOfPlayersNode *p = pNextPlayer ? pNextPlayer : pFront;
if (p && p->pData) // not sure why pData is also dynamic. look into that.
{
cout<<p->pData->getName()+" takes a turn\n";
pNextPlayer = p->pNext;
}
else
{
cout<<"There are no players. Please ADD a player.\n";
}
Each time a player's turn comes up, they take it, and the next player is that player's next pointer. When your last player at the table takes a turn, p->pNext will be null, and the next invoke will reset to the head of the list.
At least thats where I think you're trying to get. Prime this with either pNextPlayer being set to pFront or NULL; makes no difference.
Lets say you initially define pnext = NULL in while creating nodes.
So according to your code;
if (p->pData!=NULL)
{
cout<<p->pData->getName()+" takes a turn\n";
pLastPlayer = pLastPlayer->pNext;
}
else
{
cout<<"There are no players. Please ADD a player.\n";
}
There are 2 scenarios according to my assumptions:
1. p and pLastPlayer are the same ... so after the list is over. p will be equal to NULL, your code will crash as it tries to de-reference p->pData.
2. p and pLastPlayer are different ... So after the list pLastPlayer ends, the code will crash at pLastPlayer = pLastPlayer -> pNext(); as you are probably de-referencing garbage or NULL value;
You need to check for NULL pointers at some point, either in p -> pData != NULL or pLastPlayer = pLastPlayer -> pNext();
You are in C++, you are better off with a std::list than writing your own implementation.
Something's bugging me: Why are you starting your loop with "p = (*pFront).pNext" instead of starting it straight with "p = pFront"?
How are you adding your nodes to your list? You should be echo-ing "A takes a turn" before "C takes a turn".
If you are indeed adding to the front of your list (and your list is doubly-linked), you should call pPrevious instead of pNext.