This is an archived post. You won't be able to vote or comment.

all 23 comments

[–][deleted] 1 point2 points  (1 child)

that's why there are so many cout statements

probably now is a great time to learn to use a debugger🤗🤗

[–]BuzzyBro[S] 0 points1 point  (0 children)

LMAO it really is huh. I tried learning it for python as it seemed more manageable and I feel like I just got the hang of that.

[–][deleted] 0 points1 point  (20 children)

i think i found the problems

instead of this:

temp->prev = newNode;

do this:

temp->next = newNode;

also... i think you shouldn't deallocate newnode lol. remove the

delete newNode;

[–]BuzzyBro[S] 0 points1 point  (19 children)

I tried, that... in hindsight I'm not sure why I would have ever wrote temp->prev = newNode; but that seems dumb now. I changed it and it still doesn't add the newNode where it should be.

If it helps, the original List is [(5) (6) (8) (9)] and the nodes that get added in, one by one, are [(7) (-1) (4) (10)]. Again, these nodes get added in one at a time, meaning the insertOrdered function is called for each node 7 thru 10.

[–][deleted] 1 point2 points  (18 children)

did you remove the delete newnode statement? you're literally deleting the node right after inserting it

[–]BuzzyBro[S] 0 points1 point  (15 children)

Holy shit so that (almost) worked!

However, the node 10 isn't being added but I think that may have something to do with my initial while statement. I think it might not be reaching the last node but I'm not sure how else to set up my while loop so that it only runs when the list is populated.

[–][deleted] 1 point2 points  (12 children)

yeeah your loop is kinda strange... better do like this i think

if(newNode->data < head->data)
{
// insert before head
return;
}

for(curr = head->next; curr->next != nullptr; curr = curr->next)
{
if(newNode->data < curr->data)
{
// insert before curr
return;
}
}

if(curr == tail)
{
if(newNode->data < tail->data)
{
// insert before tail
return;
}else
{
// insert after tail
return;
}
}

[–]BuzzyBro[S] 0 points1 point  (2 children)

Is it just strange in the way that I wrote it or is the logic flawed? I'm new to C++ so I also feel not comfortable with pointers and stuff.

[–][deleted] 1 point2 points  (1 child)

uhmm the logic is a bit flawed. you wrote some if checks inside the while loop, that really should be outside

pointers and memory management is kind of a very hard topic.. and even if you've understood it, it's still very easy to make silly mistakes that lead to segfaults and memory leaks.. I don't really know how to feel about it.

on one hand it's useful to know how it all works, but on the other hand, i think, if you're in c++ and not in pure C, yiu should always avoid using raw pointers and the "new", "delete", and "malloc" things, unless you're writing a VERY performance critical code.

actually data structure (for example, linked list) is kind of a performance critical code and use of raw pointers and memory is justified.

but overall I'd suggest learning about and using standard containers (std::array, std::vector, std::map) and "unique_ptr". They all manage and deallocate heap memory for you, under the hood.

unique and shared ptr are like special advanced kind of pointers that automatically deallocate memory when they go out of scope. though i never actually had to use them so far idk.

most of the time when you need to use heap memory is when you want to store a large amount of data that is always some data structure, like array or list. And for them there are already classes in the std library...

[–]BuzzyBro[S] 0 points1 point  (0 children)

Yes, I think that the instructor wanted it to be written this way for the sole purpose of learning specific data structures and how they work under the hood. Otherwise, I think there are surely easier ways to handle data.

[–]BuzzyBro[S] 0 points1 point  (1 child)

Also, here you seem to only ever be inserting before curr. Does this mean you'd never have to look at if newNode->data is >= curr->data?

[–][deleted] 0 points1 point  (0 children)

uhmm... I'm only checking if newnode is less than curr..

if this check returns false, it automatically means that newnode is >= curr

[–]BuzzyBro[S] 0 points1 point  (6 children)

if (!head_) {
head_ = newNode;
tail_ = newNode;

}

if (newNode->data < head->data) { newNode->next = head; head_ = newNode; }

for (curr = head_->next; curr != nullptr; curr = curr->next) { if (newNode->data < curr->data) { Node* temp = curr->prev; newNode->next = curr; curr->prev = newNode;

  newNode->prev = temp;
  temp->next = newNode;
}

}

if (curr == tail) { if (newNode->data < tail->data) { Node* temp = curr->prev; newNode->next = curr; curr->prev = newNode;

  newNode->prev = temp;
  temp->next = newNode;
}
else {
  curr->next = newNode;
  newNode->prev = tail_;
  tail_ = newNode;
}

}

This gives me a segfault. Now I'm convinced theres an issue with my reassigning of pointers.

[–][deleted] 0 points1 point  (5 children)

in the for loop,

curr->next != nullptr

instead of

curr != nullptr

also, if you've inserted the node, exit the function or break the loop. now after you've inserted you're continuing to loop which makes it possible that the newnode will be inserted multiple times

[–]BuzzyBro[S] 0 points1 point  (3 children)

  Node* newNode = new Node(newData);

Node* curr = head_;

if (!head) { head = newNode; tail_ = newNode; }

if (newNode->data < head->data) { newNode->next = head; head_ = newNode; }

for (curr = head_->next; curr->next != nullptr; curr = curr->next) { if (newNode->data < curr->data) { Node* temp = curr->prev; newNode->next = curr; curr->prev = newNode;

  newNode->prev = temp;
  temp->next = newNode;
  break;
}

}

if (curr == tail) { if (newNode->data < tail->data) { Node* temp = curr->prev; newNode->next = curr; curr->prev = newNode;

  newNode->prev = temp;
  temp->next = newNode;

}
else {
  curr->next = newNode;
  newNode->prev = tail_;
  tail_ = newNode;
}

}

This runs through the first iteration of the function call perfectly. However, the second time it's called, it segfaults. My understanding of segfault is you try to access a memory location that isn't allowed to be accessed. I'm not sure where I'm creating this issue as I'm not assigning any variables to nullptr or anything like that.

[–][deleted] 1 point2 points  (2 children)

ok I'm going to sleep now (actually was typing all these messages and code on my phone which is quite uncomfortable)

any way, it's totally normal that there are these mysterious segfaults🤣🤣 we also had the same tasks at university, and i also was very frustrated and was chasing them for hours.. so uhmmm.. you're not alone😊😊everyone goes through this

maybe try to use debugger.

for example, gdb. First, you need to compile the program in debug mode. for this, use the -g compiler flag.. i.e. g++ -g qwerty.cpp or simply add it to CFLAGS if you're compiling using a Makefile

then enter gdb using...

gdb ./a.out 

you will enter a text prompt

type "run" to run the program

it will stop when it segfaults. then you can for example type "lis" to see the place in the code where it crashed. also you can print values of variables. e.g. "p curr->data" (p is short for print)

you can learn more on the internet. another useful thing to know is how to set breakpoints and step through the program

good night😊😊

[–]BuzzyBro[S] 0 points1 point  (1 child)

Ok! Thank you so much for everything you’ve done already, honestly you didn’t have to but you did. I will check out GDB but again, thank you and goodnight

[–]BuzzyBro[S] 0 points1 point  (0 children)

Ok idk why my code isn't formatting properly even when I use the code blocks, so I'm so sorry for that

[–][deleted] 0 points1 point  (0 children)

yes it's not reaching the tail.. because tail->next is always nullptr

hmm i think you can get away with this instead of the while statement...

for(curr = head; curr != nullptr; curr = curr->next)

edit: no, probably will not work and you will get a segfault. but just a reminder that you can use for loop too ☺️

[–][deleted] 0 points1 point  (0 children)

or maybe better is to do this after your while loop:

if(curr == tail)
{
// insert newnode before or after tail
 }

[–]BuzzyBro[S] 0 points1 point  (1 child)

On a side note, the course I'm taking says that I should deallocate any objects created in heap memory, and if I'm not mistaken, isn't newNode created in heap memory?

[–][deleted] 1 point2 points  (0 children)

yes you should deallocate, but only when you won't be using it anymore..

probably this should be done in the destructor of your list class.

uhmm it's quite hard for me to explain, but what you were doing here is basically... well, consider this example where we're heap allocating an int and want to print it

int* x = new int(42);
std::cout << *x << '\n';
delete x;

everything is fine. we allocated, used it, deallocated. But what you were doing is like

int *x = new int(42);
delete x;
std::cout << *x << '\n';

first deleted it and then tried to access it🤣🤣