C++: Pointers pointing to freed memory space - c++

The two lines of code at the bottom tail = head;
tail->next= NULL; causes the program to crash, when I call the extractMin() function. If i comment them out, everything is happening as supposed. Is this happening cause they are pointing to addresses in memory that has been freed?
The only clue the compiler gives me is this:EXC_BAD_ACCESS (code=2, address=0x0). I notice immediately the address being 0x0 so there is a problem there, but what exactly?
string LinkedListPQueue::extractMin() {
if (isEmpty())
error("Tried to dequeue from epmpty queue!");
cell *toBeDeleted = head; //pointer to this head
string value = head->value; //get value of this head
head = head->next; //move so this head is not the same as the one to be deleted
delete toBeDeleted; //delete previous head.
return value;
}
/* Implementation notes: enqueue
* -----------------------------
* We have to search to find the proper position, which can be a bit tricky with
* a singly-linked list. We walk two parallel pointers, one a step behind the other,
* until we find the correct position to insert the new cell, which we then splice
* into place. Note the special case of inserting at the head. Alternatively, this
* operation could work recursively.
*/
void LinkedListPQueue::enqueue(const string& elem) {
cell *cur, *prev, *newOne = new cell;
newOne->value = elem;
for (prev = NULL, cur = head; cur != NULL; prev=cur, cur = cur->next) {
if (elem > cur->value) break;
}
newOne->next = cur;
if (prev) {
prev->next = newOne;
logSize++;
} else {
head = newOne;
tail = head;
tail->next= NULL;
logSize++;
}

Your else clause is broken. If prev was null, then you are trying to insert before the first element.
else {
cell *oldHead = head;
head = newOne;
head->next = oldHead;
logSize++;
}
Setting tail->next = NULL is the core error.

Related

Pointer in deleting a node in single linked list

In place of *head_ref = temp->next;, why can't I assign it as *head_ref = *head_ref->next?
Why should I use temp? Aren't they pointing to the same place?
class Node{
public:
int data;
Node* next;
};
void deleteNode(Node** head_ref, int key){
Node* temp = *head_ref;
Node* prev = NULL;
if(temp!=NULL && temp->data==key){
*head_ref = temp->next;
delete temp;
return;
}
else{
while(temp!=NULL && *head_ref->data!=key){
prev = temp;
temp = temp->next;
}
}
Your code does not compile, *head_ref->data should be (*head_ref)->data.
The reason why you should use temp is that you want to modify *head_ref only if the element you want to delete is the head element. If you delete any other element of the list, the head pointer must stay the same.
But your code is wrong anyway. You're doing things in the wrong order. You must first find the element you want to delete, and then handle the deletion.
Your code handles the deletion first and then finds the element to delete which is absurd.
You want this:
void deleteNode(Node** head_ref, int key) {
Node* current = *head_ref;
Node* previous = NULL;
// find element to delete
while (current && current->data != key)
{
previous = current;
current = current->next;
}
// if current is NULL here then the element has not been found
if (current != NULL)
{
// element found,
// current points to element found
// previous points to previous element or NULL if current is head
if (previous == NULL)
{
// deleting head element -> we need to update head_ref
*head_ref = current->next;
}
else
{
// deleting any other element -> update next pointer of previous element
previous->next = current->next;
}
delete current;
}
}
That being said, this is rather C code than C++ code. You should use standard containers rather than making your own, or at least use C++ idioms such as constructors.

Why does destructor run into unallocated memory?

I have a singly-linked, circular linked list and am writing a destructor to delete all the nodes. The destructor first severs the head from the rest of the lest to prevent infinite circulation and then I loop through the list and delete all the nodes, eventually, the loop comes back to the head and deletes it as well. In the program I check to make sure that the pointer to the nodes is not NULL and I ran the debugger and it shows that it is NULL at a point which should end the loop, but instead the loop continues and runs into un-allocated memory. Here is my code:
node<T> *cur = head;
node<T> *nxt = head->next;
if (nxt) cur->next = nullptr;
cur = nxt;
// walk through the list and delete nodes
while (cur) {
cur = cur->next;
delete cur;
}
EDIT: Changed code to
node<T> *cur = head;
node<T> *nxt = head->next;
if (nxt) cur->next = nullptr;
cur = nxt;
// walk through the list and delete nodes
while (cur) {
nxt = cur->next;
delete cur;
cur = nxt;
}
EDIT 2: Changed code once more to handle edge cases, same problem still occurs.
if (head == NULL) return;
else if (head->next == head) delete head;
else {
node<T> *cur = head;
node<T> *nxt = head->next;
cur->next = nullptr;
cur = nxt;
while(cur) {
nxt = cur -> next;
delete cur;
cur = nxt;
}
}
It has nothing to do with the severing, your code to walk the list while deleting elements would be just as faulty in a non-circular list. You advance the pointer then delete what it points to (the next item).
You need to delete the current item (but, of course, you also need to have extracted its next field before that point because, once deleted, all content becomes undefined), something like:
while (cur != nullptr) {
node<T> *toDelete = cur;
cur = cur->next;
delete toDelete;
}
In terms of a full solution to what you need, the algorithm should be:
def delCircList(head):
# Ignore empty list.
if head == null:
return
# Special for one-element list.
if head.next == head:
free head
return
# Sever link and set start point.
curr = head.next
head.next = null
# Use normal deletion algorithm.
while curr != null:
toDelete = curr
curr = curr.next
free toDelete

What's wrong with the insert at the end operation in this Linked List?

I have written this code for implementing Linked List in c++. It worked perfectly till i added the insert at end function to it. Please see what's wrong! Without the insertatend function, output is correct. After adding that function, the output is 1 10 which is actually the insert at start and end's outputs.
void List::insertatend(int num)
{
Node *new_node=new Node(num);
if(listptr==NULL)
listptr=new_node;
else
for(Node *temp=listptr; temp->next!=NULL; temp=temp->next)
temp->next=new_node;
}
The problem is in the lines:
for(Node *temp=listptr; temp->next!=NULL; temp=temp->next)
temp->next=new_node;
It seems like you haven't walked through the logic of how the code works.
You will first need to iterate until temp->next is NULL and then use
temp->next=new_node;
The code to implement that logic is:
Node* temp = listptr;
for ( ; temp->next != NULL; temp = temp->next )
{
// Do nothing in the loop.
}
temp->next = new_node;
Here's the updated function:
void List::insertatend(int num)
{
Node* new_node = new Node(num);
if( listptr == NULL)
{
listptr = new_node;
}
else
{
Node* temp = listptr;
for ( ; temp->next != NULL; temp = temp->next )
{
}
temp->next = new_node;
}
}
Go through the basic logic of how to add the every new node at end of previous node.Bug is in below two lines of insertatend function, explanation I mentioned in comments.
for(Node *temp=listptr; temp->next!=NULL; temp=temp->next) //it should be dummy loop
temp->next=new_node;//In all old nodes next part will replace by new_node which is wrong
Modiy Insert_end() function as
void List::insertatend(int num)
{
Node *new_node=new Node(num);
if(listptr==NULL)
listptr=new_node;
else{
Node *temp=listptr;
for( temp ; temp->next!=NULL ; temp=temp->next); /** rotate dummy loop until temp is not reaching to last node **/
temp->next = new_node;// in last node next put the new node address
new_node->next = 0; // and new node nnext put the zero
}
}

Why wont my Insert function for a list make new nodes?

Hello My problem with this code is on my 2nd else loop; i never enter it and therefore i never make new nodes for my list. can anyone help me see what i am missing?
bool List::Insert(int data)
{
Node* P = new Node;
if(P==NULL)
{
return false;
}
else
{
P ->info = data;
P ->next = NULL;
if(Head == NULL)
{
Head = P;
}
else
{
Node* lastNode;
for(lastNode = Head; lastNode ->next != NULL; lastNode = lastNode ->next)
{
lastNode ->next = P;
}
}
return true;
}
}
This:
Node* lastNode;
for(lastNode = Head; lastNode ->next != NULL; lastNode = lastNode ->next)
{
lastNode ->next = P;
}
is dead wrong. It will change the next pointer, for every single node currently in the list, to point to your new node. You need to only change the pointer in the last node:
Node* lastNode = Head;
while (lastNode->next != NULL)
lastNode = lastNode->next;
lastNode->next = P;
You may also, for efficiency, want to maintain a separate Tail pointer (in addition to your Head) so that you can simply replace that whole operation with:
Tail->next = P;
Tail = P;
That way, you won't have to traverse the entire list every time you want to append a new node. Your code then becomes something like (without the traversal, and with updating the tail pointer as well):
// Prepare new node.
Node *P = new Node;
P->info = data;
P->next = NULL;
// If list empty, set head and tail to new node, otherwise
// append it.
if (Head == NULL) {
Head = P;
Tail = P;
} else {
Tail->next = P;
Tail = P;
}
I'll stop short of criticising the fact that your Insert method doesn't actually insert but rather appends. My near-anal-retentive nitpicking nature is unlikely to endear me to you:-)
lastNode ->next = P; // this must go after the for

Implementing push/pop in a linked list (C++)

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);