I am trying to find the node where the cycle begins in the list. The result returned is correct. However, an error stating * Error in ./solution: double free or corruption (fasttop): 0x0000000000b3e030
Aborted is shown. I saw some other similar problems, and I think the problem is with temp1=temp;. But I don't know how to solve this problem.
How to correct it? Also why is this error occurring?
ListNode* Solution::detectCycle(ListNode* A) {
ListNode* temp = A;
ListNode* temp1 = A;
while(temp->next!=NULL && temp->next->next!=A->next ){
temp1 = temp;
temp = temp->next;
temp1->next=A->next;
}
if(temp->next==NULL) {
temp->val=-1;
delete temp1;
return temp;
}
else {
temp= temp->next;
delete temp1;
return temp;
}
}
Thank you.
As a direct answer, your code is crashing because your are accessing nodes that are already free. Beyond accessing, you are deleting a node that has already been deleted. This 'double free' will almost alway result in a crash or other chaos. A strong understanding of heap mechanics in C/C++ will save you a lot of misery, it is worth studying.
I'm not too sure what the requirements are but I believe your are trying to check for a circular linked list. I not clear why you are deleting any of the nodes in a 'detect' method. Are you trying to break the loop? If so, all of the node will still be in the list so nothing will be deleted, just change the ->next to nullptr on the node that loops back.
Here is some example code from your original. I created it using your code as a base and then using the gdb debugger to debug it. An effective software engineer is a master of the debugger, embrace it. It is a Minimal, Complete and Verifiable example as described in the comments.
I put a few tests as an example of 'use cases', no loop, degenerate loop, longer loop. As software engineers, a big part of our job is thinking about error cases which often occur on the boundaries. There may be others that I have not covered.
As noted in the comments, compiling or a single successful use case doesn't indicate defect free software. Rigorous testing is needed to gain confidence. This kind of testing is often referred to as 'unit testing' there is a large body of literature on the subject.
#include <iostream>
struct ListNode
{
int val;
ListNode* next;
};
//Look for a loop back to A
ListNode* detectCycle(ListNode* A) {
if(A == nullptr) // can't be a loop if list is empty
return nullptr;
ListNode* temp = A;
while(temp->next!=NULL && temp->next !=A ){
temp = temp->next;
}
if(temp->next==NULL) {
return nullptr; // No loop
}
else {
return temp; // Node where loop starts, may be A itself
}
}
int main(int argc,char* arv[])
{
ListNode *a = new ListNode;
ListNode *loop = nullptr;
loop = detectCycle(a);
if(loop == nullptr)
std::cout << "Case 1 passed" << std::endl;
a->next = a;
loop = detectCycle(a);
if(loop == a)
std::cout << "Case 2 passed" << std::endl;
ListNode *b = new ListNode;
ListNode *c = new ListNode;
ListNode *d = new ListNode;
a->next = b;
b->next = c;
c->next = d;
d->next = a;
loop = detectCycle(a);
if(loop == d)
std::cout << "Case 3 passed" << std::endl;
loop = detectCycle(b);
if(loop == a)
std::cout << "Case 4 passed" << std::endl;
return 0;
}
Related
I'm trying to add numbers from two linked lists and put it in a third one. It adds well but my code blocks compiler stops responding while running this code possibly because of an infinite loop or some exception.
Following code adds two numbers stored in reverse order in a linked list.
struct Node{
int x;
Node* next;
};
class LinkedList{
public:
Node* head;
LinkedList(){
head = NULL;
}
void addNode(int num){
Node* n = new Node();
n->x = num;
n->next = NULL;
if(head == NULL){
head = n;
}else{
Node* n1 = head;
while(n1 != NULL){
if(n1->next == NULL){
n1->next = n;
break;
}
n1 = n1->next;
}
}
}
int popNode(){
int num = NULL;
if (head != NULL){
num = head->x;
head = head->next;
}else{
cout << "Yay" << "\n";
num = NULL;
}
return num;
}
void printList(){
Node* n1 = head;
while(n1 != NULL){
if(n1->next == NULL){
cout << n1->x << "\n";
}else{
cout << n1->x << "->";
}
n1 = n1->next;
}
}
};
LinkedList* add_nums(LinkedList* l1, LinkedList* l2) {
LinkedList l3;
int num1= (*l1).popNode();
int num2= (*l2).popNode();
int carry = 0;
while(num1 != NULL || num2 != NULL){
int num3 = num1+num2+carry;
if (num3 > 9){
int temp = num3 % 10;
carry = (num3 - temp)/10;
num3 = temp;
}
l3.addNode(num3);
l3.printList();
num1 = (*l1).popNode();
num2 = (*l2).popNode();
}
return &l3;
}
int main(int argc, char const *argv[]) {
LinkedList list1;
LinkedList list2;
list1.addNode(2);
list1.addNode(4);
list1.addNode(3);
list2.addNode(5);
list2.addNode(6);
list2.addNode(4);
(*(add_nums(&list1, &list2))).printList();
return 0;
}
Can anyone tell me what I'm doing wrong?
Changes to code i should do after inputs from answers below:
I should change integer initializations from NULL to 0.
Should use LinkedList objects to terminate my loop.
Should change how i access the functions from a pointer
Thanks everyone.
Can anyone tell me what I'm doing wrong?
IMHO you might be making a wrong choice. The STL provides data structures for (doubly linked) list and forward list (which is singly linked). Maybe you want to use those. You can expect them to be efficient enough, bug free and important to know about if you want to be a proficient C++ programmer.
It would make sense to let someone do a code review (there is a code review StackExchange site); e.g. naming the integer variable x in the linked list is probably not considered a good practise.
You did not tell us what is wrong about your program. This is expected in SO. Your question qualifies for "off-topic (why is this code not working?)". You provided the program, which is good. But you did not provide your expected input and output. What is your program expected to do? If I consider your main function as a test, then what result did you expect ?
see below some errors/warnings
In the function popNode
int num = NULL; // should be 0, it's an integer
...
num = NULL; // same reason
In the functions add_nums
LinkedList l3; // it's a local variable (see return below)
...
while(num1 != NULL || num2 != NULL) // again num1 and num2 are integers
....
return &l3; // address of a local variable :-(
I think it is better you declare the variable l3 as a pointer to LinkedList:
LinkedList *l3 = new LinkedList;
... // adapt the code to use l3 appropriately
return l3;
As others in comments say, your error is this one: return &l3;
l3 is a local object and is deleted just before the end of the function, like any object that is not dinamically allocated. This is because of the scope of your LinkedList object.
You should have written:
LinkedList* l3 = new LinkedList();
//...
//...
return l3;
this function now returns a pointer to your object.
NB: the variable l3, which contains the pointer, is deleted just before the function, but it doesn't matter because the object lifetime is not bound to the function anymore.
The following code builds correctly but causes the program to crash when I run it. Can someone please tell me whats wrong with it. I suspect that there is something wrong with the DeleteNode function.
#include <iostream>
#include <cstdlib>
using namespace std;
class list {
private:
typedef struct node {
int data;
node* next;
}* nodePtr; //this means that 'nodePtr' will mean a pointer to the struct node
nodePtr head;
nodePtr current;
nodePtr temp;
public:
list() { //constuctor
head = NULL;
current = NULL;
temp = NULL;
};
void AddNode(int addData) //to add a particular data value
{
nodePtr n= new node;
n->next = NULL;
n->data = addData;
if (head != NULL) { //if a list is already set up
current = head;
while (current->next != NULL) { //to get to the last node in the list
current = current->next;
}
current->next = n;
}
else { // if list is not created
head = n; //new node is front of the list
}
}
void DeleteNode(int delData) //to delete a particular data value
{
nodePtr delPtr = NULL;
temp = head;
current = head;
while (current != NULL && current->data!=delData) { //pass through whole list && find value
temp = current;
current = current->next;
}
if (current = NULL) { //data value not found in list
cout << delData << " was not in the list." << endl;
delete delPtr; //to free up memory space
}
else {
delPtr = current;
current = current->next;
temp->next = current; //to reconnect list
if (delPtr == head) {
head = head->next;
temp = head;
}
delete delPtr;
cout << "The value " << delData << "was deleted." << endl;
}
}
void PrintList() //to print all the data values
{
current = head;
while (current != NULL) { //to go through the data valued of the list
cout << current->data << endl;
current = current->next;
}
}
};
int main()
{
list Shahzad;
Shahzad.AddNode(2);
Shahzad.AddNode(78);
Shahzad.AddNode(28);
Shahzad.AddNode(2398);
Shahzad.DeleteNode(78);
Shahzad.PrintList();
return 0;
}
Your first problem is with the following line:
if (current = NULL)
You're actually assigning null to current at this point.
This should actually be:
if (current == NULL)
Firstly, few code and file management remarks: consider separating your code into .h file where class members are declared and .cpp where class members are implemented, this will make your class easy to comprehend and possible errors will be easier to locate.
Secondly, a general advice when dealing with structures containing pointers is attention to proper resource management, i.e. pointer definitions, initialisations and deletions should be dealt with caution. If you are novice, consider the use of already provided smart pointer facilities like: std::unique_ptr which will "retain sole ownership of an object through a pointer and destroys that object when the unique_ptr goes out of scope"
Thirdly, use debugger to get rid of trivial errors like:
if (current = NULL)
which by the way contains additional inaccuracy expressed in the use of NULL instead of the pointer literal nullptr.
Lastly, check each of the member functions separately after you finish the initial implementation and only then proceed with further class expansion, otherwise you risk the accumulation of errors from multiple sources which will make your job very difficult
In your delete function in the case of which the node isn't found, you are deleting delPtr.
However, delPtr was never instantiated or assigned so you are trying to delete something that doesn't exist.
Always enclose pointer deletions in if statements to avoid this issue. Try this:
if (delPtr) delete delPtr;
Apart from all the suggestions here, you can use some safe programming practices to catch bugs early.
For ex: you wrote
if (current = NULL)
Instead, try writing the value being checked on the LHS and the variable on the RHS like this:
if ( NULL == current)
Here, if you mistyped
if (NULL = current)
the compiler will complain. You have a compile time bug now instead of a run-time one. This is far easier to find and debug.
It seems that I can't figure out why the while loop wont terminate.
It should be while(null) essentially.
I can't figure it out.
All help would be appreciated :D
I dont know what could possibly be stopping the while loop at all? It says that the first entry gets stored, and the entry for next is at 0x0000000000 and ??? name and ??? ??? coords so it is in fact NULL. I tried adding in the constructor next = 0; instead of next = NULL and it still did not work.
Thanks guys.
Anthony
EDIT: Value of nodePtr = 00000000 if next = 0 in the constructor
Value of nodePtr = 00899FE0 if next = NULL in the constructor
if adding a cout << nodePtr->next; before the while.
http://pastebin.com/7usYdfHB -- Full program for reference.
EDIT2:
Is the popup when I go to enter the 2nd entry.
void LinkedList::appendNode(string name, double x, double y)
{
ListNode* newNode; // To point to new node
ListNode* nodePtr; // To traverse List
// allocate new node
newNode = new ListNode(name, x, y);
// If no head, head is the newNode
// else traverse the list to find the end and append newNode
if (!head)
{
head = newNode;
cout << "Record inserted successfully.\n" << endl;
}
else
{
nodePtr = head;
//traverse the list loop
while (nodePtr->next) //VS 2012 locks up here <-----
{
//Checks for duplicate entry by name
if (nodePtr->cityName == name)
{
cout << "No need to insert again, as this record exists in the existing data set.\n" << endl;
return;
}
//traverse the list
nodePtr = nodePtr->next;
}
// checks 2nd entry, as while loop wont run for a 2nd entry.
if (nodePtr->cityName == name) {
{
cout << "No need to insert again, as this record exists in the existing data set.\n" << endl;
return;
}
}
// if next is NULL add newNode
else if (!nodePtr->next)
{
nodePtr->next = newNode;
cout << "Record inserted successfully.\n" << endl;
}
}
Aside from the obvious memory leak when an attempt to insert an already existing name is made, your code seems to work fine. It works fine when either 0 or NULL is used to initialize the pointers. It makes no difference.
(One wild guess I can make is that in your actual calling code (which you do not show), you somehow managed to pass your LinkedList around by value. Since your LinkedList does not satisfy the Rule of Three, the integrity of the list got violated, which lead to undefined consequences you observed.)
BTW, by using an extra level of indirection you can simplify your heavily branched appendNode function into a significantly more compact and almost branchless one
void LinkedList::appendNode(string name, double x, double y)
{
ListNode** pnodePtr;
for (pnodePtr = &head; *pnodePtr != NULL; pnodePtr = &(*pnodePtr)->next)
if ((*pnodePtr)->cityName == name)
break;
if (*pnodePtr == NULL)
{
*pnodePtr = new ListNode(name, x, y);
cout << "Record inserted successfully.\n" << endl;
}
else
cout << "No need to insert again, as this record exists in the existing data set.\n" << endl;
}
(I also eliminated the leak.) Specifically, this technique allows one to avoid writing a dedicated branch for processing the head node.
Also (referring to the full version of the code), in your functions from "delete by coordinate" group you for some reason check both x and y coordinates of the head node, but only one coordinate of the other nodes down the list. Why? This is rather weird and does not seem to make much sense. Meanwhile, functions from "search by coordinate" group do not have this issue - they process all nodes consistently.
Also, your displayList function suffers from a stray return at the very beginning, which is why it never prints anything. You need to add a pair of {} to properly group your statements.
I tried to reproduce your problem but could not. I reverse engineered your ListNode and LinkedList classes. The code below works, maybe that will help you sort out your issue. I refactored it a little to simplify it (going further you should consider keeping track of the end of the list as this will help with other operations that your list will need). Be sure to implement a destructor for your LinkedList class to clean up the nodes.
#include <string>
#include <iostream>
using namespace std;
struct ListNode
{
string cityName;
double m_x, m_y;
ListNode* next;
ListNode(string name, double x, double y) : cityName(name), m_x(x), m_y(y), next(nullptr)
{}
};
class LinkedList
{
ListNode* head;
public:
LinkedList() : head(nullptr)
{
}
~LinkedList()
{
}
void LinkedList::appendNode(string name, double x, double y)
{
ListNode* newNode; // To point to new node
// allocate new node
newNode = new ListNode(name, x, y);
// If no head, head is the newNode
// else traverse the list to find the end and append newNode
if (!head)
{
head = newNode;
cout << "Record inserted successfully.\n" << endl;
}
else
{
ListNode *nodePtr = head;
ListNode *prevNode = nullptr;
//traverse the list loop
while (nodePtr)
{
//Checks for duplicate entry by name
if (nodePtr->cityName == name)
{
cout << "No need to insert again, as this record exists in the existing data set.\n" << endl;
return;
}
//traverse the list
prevNode = nodePtr;
nodePtr = nodePtr->next;
}
// if next is NULL add newNode
if (prevNode)
{
prevNode->next = newNode;
cout << "Record inserted successfully.\n" << endl;
}
}
}
};
int main()
{
LinkedList list;
list.appendNode("New York", 1.0, 2.0);
list.appendNode("Boston", 1.5, 2.5);
list.appendNode("Miami", 1.7, 2.7);
list.appendNode("Miami", 1.7, 2.7);
}
The following code is part of my implementation for a class member function that rents lockers and thus creates nodes in a linked list:
void SelfStorageList::rentLocker(Locker e) {
int count = 0;
LockerNode *p = head;
if (isEmpty()) {
head = new LockerNode(e, head);
tail = head;
}
LockerNode *prev = head;
LockerNode *curr = head->next;
for( ; curr != 0 && curr->objLocker.isVip; prev = prev->next, curr = curr->next) {
if(count == 1) {
if (e.isVip) {
if(p->objLocker.isVip) {
LockerNode *p = new LockerNode(e, p->next);
}
else {
LockerNode *p = new LockerNode(e,head);
}
}
//etc...
When I run it, I get two errors that my *p pointers may potentially be uninitialized. I don't think they would pose any sort of run time error issues, but the program will not compile as long as the errors persist. I was wondering what alternative I might have to the current implementation of the
LockerNode *p = new LockerNode(e, p->next);
and
LockerNode *p = new LockerNode(e,head);
lines. All I want them to do is to create new nodes with the passed in info element of e, either before the current listed locker or after, depending on the condition.
Thanks for any help provided! Let me know if it would be useful to post any other particular parts of the code, although it is quite lengthy, so I was hoping to avoid posting it all and isolating the problem into a manageable module.
In this if-else, you are declaring a new pointer p in each block:
if(p->objLocker.isVip) {
LockerNode *p = new LockerNode(e, p->next);
}
else {
LockerNode *p = new LockerNode(e,head);
}
Each one of these is local to the scope. It results in a memory leak, and has no effect on the p from the outer scope.
OK, first I have my node structure
struct node {
string s;
node * next;
};
And It's located within a class
class strSet{
private:
node * first;
And I can construct the list, and i've made checks to see it's being constructed (it is), but when i try and print it.. "Empty Set" is printed
This is my code to "print" it: (I've tried many variations of declaring a temp pointer, and still nothing)
node *temp = new node;
temp = first;
if (temp == NULL) cout << "Empty set" << endl;
else {
// node * temp = new node;
while (temp != NULL){
cout << temp->s << endl;
temp = temp->next;
}
}
Any help is appreciated, Thanks
EDIT: I have a function that makes a singleton list (this is for an assignment), the code is:
node *first = new node;
first->s = s;
cout << first->s << endl;
first->next = NULL;
The third line prints out the element when I add it
And yes i know there is a memory leak
node *temp = new node;
this line is unnecessary and leaks memory;
The rest of the printing routine is correct, and therefore if "Empty Set" is printer therefore the set IS empty
From the small quantity of code you posted, it should work, so my guess would be that something is wrong with the construction of the list.
Now, there are some incoherences in your code - the useless "new node" for temp, as stated, but also having your (temp == NULL) ; this test could be directly operated with "first". Of course, make sure the strSet initializes first to null.
Then only you'd create temp before the while() and after the else. It's more logical (and a bit more optimal, though you're not winning much there - but you'll gain in readability).
node *temp = new node;
temp = first;
can be condensed to -
node *temp = first ; // An unnecessary memory leak in earlier case.
Other than that print logic seems to fine. You didn't show the important part of how the linked list is formed.
node *first = new node;
first->s = s;
cout << first->s << endl;
first->next = NULL;
This is not a linked list at all. You are just creating an instance of type node* and just copying the s to it.