Segfault when accessing non-null pointer? - c++

The code works fine in a Linux environment, but in Windows it crashes 5-10 seconds after the program starts. The debugger points to n->fired = true; as the problem?
void ParticleSystem::PrivProcessParticles(pNodePtr n, double frameTime)
{
while(n != NULL) {
n->fired = true;
if(!n->immortal)
n->life -= frameTime; //Decrement life
n->particle.ApplyAccel2D(frameTime);
/* Since the oldest particles will always be on
top of the queue, if life is zero, dequeue! */
if(n->life <= 0) {
if(head != NULL && !n->immortal) {
pNodePtr curr;
curr = head;
head = head->next;
delete curr;
}
}
n = n->next;
}
}
Allocation:
void ParticleSystem::AddParticle(double lifeIn, double x, double y, double angle,
double size, double force, bool immortalIn)
{
//Increment particle count
count++;
//Allocate
pNodePtr n = new particleNode;
//Initialize
n->particle.CreateQuad(size);
n->particle.SetTexture(texture);
n->particle.SetPos2D(x, y);
n->particle.SetRot2D(angle);
n->particle.SetTopSpeed(topSpeed);
n->particle.SetVelocity(force);
n->life = lifeIn;
n->immortal=immortalIn;
n->fired = false;
n->next = NULL;
//Place
if (head == NULL)
{
head = n;
tail = n;
n->next = NULL;
} else {
tail->next = n;
tail = n;
}
}
Node:
struct particleNode {
Quad particle;
double life;
bool fired;
bool immortal;
particleNode* next;
};

There's not enough information posted. However, here's one potential source of the problem.
When your PrivProcessParticles function performs its iterations over n, it can decide to delete head element of your list. But is it possible that at the moment when it decides to delete head, n is actually the same as head? If so, deleting head turns n into a dangling pointer, which leads to disastrous consequences at n = n->next.
Add assert(curr != n) before delete curr and see whether that assertion holds or fails.
Anyway, what is the starting value of n passed to PrivProcessParticles by the caller? Can it by any chance happen to be the same as head?
P.S. Also, just out of curiosity, the logic that you use to decide whether to perform the deletion or not seems to suggest that the decision is actually made about node n (you check n->life <= 0 and n->immortal). But then you proceed to delete head, not n... Is that by design?
P.P.S. A nitpick: you are doing excessive n->next = NULL initializations in your AddParticle.

Related

Struct pointers are overriding each other

I have a function:
void initGraph(node_t *node, const int orderedInputNodes[]) {
int index;
for (int i = 0; i < S * 2; i++) {
if (orderedInputNodes[i] == node->number) {
index = i % 2 == 0 ? i + 1 : i - 1;
node_t newNode;
newNode.number = orderedInputNodes[index];
newNode.left = EMPTY;
newNode.right = EMPTY;
if (node->left == EMPTY) {
node->left = &newNode;
}
else if (node->right == EMPTY) {
node->right = &newNode;
}
}
}
.
.
.
}
Everytime I find a corresponding number I create newNode, assign its value to it and pass it either to the left or to the right, however, when the code comes to the part when the right child is being assigned, the left child gets overwritten. How come is that? I thought by stating node_t newNode; a completely new node will be automatically created.
I thought by stating node_t newNode; a completely new node will be automatically created.
Correct. The problem is that the new node can replace the old node. Consider:
for (int j = 0; j < 1000; ++j)
{
int i;
i = 3;
}
You don't think after this loop runs, there's a thousand instances of i still sitting around, do you? Every time this bit of code runs, a new i is created. But every time this bit of code runs, the i from the previous iteration doesn't exist anymore because it goes out of scope.
You have:
{
node_t newNode; // newNode is created here
newNode.number = orderedInputNodes[index];
newNode.left = EMPTY;
newNode.right = EMPTY;
if (node->left == EMPTY) {
node->left = &newNode; // you save a pointer to it here
}
else if (node->right == EMPTY) {
node->right = &newNode;
}
}
// but newNode doesn't exist anymore here
So you've saved a pointer to an object that no longer exists. It winds up pointing to whatever happens to be stored in that memory, likely the next newNode that is created on the next pass in the loop.
Don't store pointers to local objects.
Update: You say you're coding in C++. Why are you using raw pointers then? Do you really want to manually manage the lifetimes of objects? C++ has fantastic tools to make this easy like std::unique_ptr.

Sieve of Eratosthenes C++ using single linked list

Hi I have a problem with Sieve of Eratosthenes in C++. I have to do this using single linked list. My program is running and showing first declaration of list but I don't know how to delete non prime numbers properly. My function just isn't working for me. How should I change my delete function?
#include <iostream>
#include <cmath>
using namespace std;
struct List
{
int number;
List* next;
};
List* head = new List;
void l_add(int n)
{
List* temp = head;
for (int i = 2; i <= n; i++)
{
temp->next = new List();
temp->number = i;
temp = temp->next;
}
}
void l_print()
{
List* temp = head;
while (temp->next != 0)
{
cout << temp->number << " ";
temp = temp->next;
}
cout << endl;
}
void l_delete(int n)
{
List* temp = head;
for (int i = 2; i < sqrt(n); i++)
{
if (temp->number % i == 0)
{
head = temp->next;
delete temp;
temp = head;
}
while (temp->next != 0)
{
if (temp->next->number % i == 0)
{
temp->next = temp->next->next;
delete temp->next;
}
temp = temp->next;
}
}
}
int main()
{
int n;
cout << "Enter up to which number to find prime numbers using Sieve of Eratosthenes: " << endl;
cin >> n;
l_add(n);
l_print();
l_delete(n);
l_print();
return 0;
}
This would be a working version of the l_delete method:
void l_delete(int n)
{
List* temp = head;
for (int i = 2; i < sqrt(n); i++)
{
while (temp->next != 0)
{
if (temp->next->number % i == 0 && temp->next->number != i)
{
List* temp2 = temp->next->next;
delete temp->next;
temp->next = temp2;
}
if(temp->next == 0) break;
temp = temp->next;
}
temp = head;
if (temp->number % i == 0 && temp->number != i)
{
head = temp->next;
delete temp;
temp = head;
}
}
}
There were several problems with your deletion method.
Problems with algorithm logic: With your algorithm head should be checked last because otherwise if its deleted, the new head is not checked for primality, you immediately check new next, which is old ->next->next. Also you didn't check if number is equal to divider in which case it should not be deleted.
Problems with programming logic:
When you're deleting next node in the while loop, same as when deleting head, you need another temporary variable to store temp->next->next and then after deleting assign it to temp->next.
But the biggest problem here is that this is not Eratosthenes sieve at all, you are
just checking all numbers for divisibility with all others smaller than sqrt(n). It
is suboptimal compared to the Eratosthenes sieve. If you Google Eratosthenes sieve, you’ll find a lot of detailed tutorials and explanations.
I like what Bran is pitching, and I'm going to add a few tricks.
Comment: Global variables suck. They make things harder to trace when projects get bigger. I'd move head into main and pass it around as a parameter. I'm also ditching the sentry node because I find them more trouble than they are worth most of the time.
int main()
{
int n;
cout << "Enter up to which number to find prime numbers using Sieve of Eratosthenes: " << endl;
if (cin >> n)
{
// should be a bit more logic here to automatically handle ns of 1 or 2
List* head = nullptr; // not using a sentinel node
l_add(head, n); // passing in head rather than global variable free-for-all
l_delete(head);
l_print(head);
return 0;
}
else
{
cout << "invalid input." << endl;
return 1;
}
}
When adding to the linked list, you don't need any even numbers other than 2. So don't add them. Less time spent iterating the list. After that it's a matter of making sure nodes go in in the right order.
void l_add(List*& head, // passing in head. Easier to track
int n)
{
List** temp = &head; // head is a next pointer with a different name
// hiding it behind another pointer allows us to treat
// it like a next
// temp is now a pointer to next pointers. We can add directly to the
// last nodes's next pointer and also use it to access the current
// pointer if we need to
(*temp) = new List {2, nullptr}; // 2 is only even prime
temp = &(*temp)->next;
for (int i = 3; i <= n; i+=2) // start at 3 and only add odd numbers
{
(*temp) = new List {i, nullptr};
temp = &(*temp)->next; // Advance to next node
}
}
When we're iterating through the list looking to eliminate multiples we need two loops. One to keep track of the node we're eliminating multiples and another loop to do the hunting and eliminating. Note that I'm using the pointer-to-pointer trick again. This trick annihilates about half of the code needed to traverse and remove nodes.
void l_delete(List * head)
{
List* last = head->next; // track the last known prime node. skip node 2.
// note this will blow up if there is no node 2.
while (last) // for every node still in the list
{
List** current = &last->next; // similar to trick above.
// if we have a pointer to the next to be
// updated, we don't need to track the previous node
while ((*current)) // look at every node after the last prime
{
if ((*current)->number % last->number == 0) // if it's a multiple, remove it.
{
List * to_del = (*current); //save node to delete
(*current) = (*current)->next; // link previous node to next node.
// effectively automatically advances the node
delete to_del;
}
else // proceed to next node
{
current = &(*current)->next;
}
}
last = last->next; // advance to next prime number
}
}
Probably plenty of room in there for optimization, but I'm aiming more for readability because if I drop ten lines of cryptic gibberish nobody learns nuthin'.

Deallocating memory from a linked list

I'm trying to delete the n'th element, which is a random number from 1 to n.
My code does this fine (correct element is deleted and surrounding elemnts are connected) but when it comes to being efficient, it is crashing when I un-comment the line delete (nodeToRemove); and I'm not sure why. Does anyone have any insight?
Assuming my struct looks like :
struct Node {
int data; // The data being stored at the node
Node *next; // Pointer to the next node
};
//------------------------------------------------------------------------------
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
head = head->next;
}
else
{
for (int i = 1; i < random - 1; i++)
temp = temp->next;
nodeToRemove = temp->next;
temp->next = temp->next->next;
}
// delete (nodeToRemove); <----- uncommenting this leads to crash,
}//end deleteNthElement()
//------------------------------------------
int main()
{
Node *head = NULL;
Node *temp;
Node *listarray[n[i]];
int n[] = {1000, 5000, 9000, 105000, 400000, 500000, 505000, 800000, 995000, 1000000};
for (int j = 0; j < n[i]; j++)
listarray[j] = new (Node);
//start timer
begin = clock();
//fill it
for (int j = 0; j < n[i]; j++)
{
listarray[j]->data = (rand() % n[i] + 1);
insertNodeInOrder (head, temp, listarray[j]);
}
//delete it
for (int j = 0; j < n[i]; j++)
deleteNthElement (head, temp, (rand() % (n[i] - j) + 1));
//deallocate
for (int j = 0; j < n[i]; j++)
delete listarray[j];
delete *listarray;
//end timer
}
You're picking the wrong Node, you want:
...
nodeToRemove = temp;
...
At least, you have to check for the end of the list, that is, you need to avoid access to null pointers (i really hope you set next to 0 at the end of the list). If you add the allocation parts, I will extend my answer.
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
if(head != 0)
head = head->next;
} else {
for (int i = 1; i < random - 1; i++)
if(temp != 0)
temp = temp->next;
else throw 1; // no such index; throw something more verbose :)
if(temp == 0)
throw 1; // same situation as above
nodeToRemove = temp->next;
if(nodeToRemove == 0)
throw 1; // same situation as above
temp->next = temp->next->next;
}
if(nodeToRemove == 0)
throw 1; //no such index; ... as the above 3
delete nodeToRemove;
}//end deleteNthElement()
Some clean-up first:
Why pass in two pointers here? do you need the value of temp out? If so why not return it?
Also why the node * & temp? (I can see why it is done for head).
int random should probably be called something like index as it describes the functionality better (as far as the function is concerned, there is nothing random about it).
The same with temp.
I propose:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
//...
We don't need temp if we are removing the head. Also, we generally 0 index things, so we should reflect that too. Thus it becomes:
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
Now we get to the main bit. The loop is just there to step through to the parent node of the node to delete, so we can simplify it a little and add checks to make sure we can't 'fall off' the end of the list.
We then have to make sure there is a node to remove, (so another check). We don't need to check for a node beyond as assigning nullptr isn't a problem (I am assuming that an invalid pointer is set to nullptr here):
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
Incidentally, this fixes a probable off by one error. Which is probably your problem (did it crash every time? only when deleting the last element? next to last?
Now we just need to delete it.
Putting it all together:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
else
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
delete node_to_remove;
return;
}
And that should work fine. The checks will prevent us dereferencing null pointers which was (probably) what caused you to crash. Can't tell without full code.

Traversing linked list and modifying or inserting node C++

I am attempting to write a function that will traverse a linked list, wherein the nodes represent terms of a polynomial. Each node includes fields for coefficient (a double named coeff), power (a size_t named power), and link (a NodePtr *next). The function is called with a double variable value, which represents the coefficient the node should have, and a size_t variable i, which represents its power. The function should traverse the linked list looking for the node with power i. If the list already contains a node with power i, its coefficient should be changed to hold the new value. If it did not previously have a node with power i, such a term should be added with the coefficient value. The list should be ordered by power (i.e. the node with power 3 should be the node 3 in the list).
Below is the code I have written thus far, though it currently generates the following error:
Unhandled exception at 0x0130D2FA in Project 3.exe: 0xC0000005: Access violation writing location 0x0000000C.
I cannot figure out why the error is generated, so that is my first issue. The second is that I believe my function may have some logical errors and does not correctly modify and create new nodes.
I have been stumped on this for days and cannot test my other functions without this having this one in working order, so any help would be greatly appreciated! Thank you!
void Poly::setCoeff(double value, size_t i)
{
if (0 <= i){
Node* prev = new Node();
Node* curr = new Node();
Node* newNode = new Node();
newNode->coeff = value;
newNode->power = i;
curr = myHead; // Initialize curr to myHead;
if (curr != nullptr)
{
while (curr->next != nullptr && curr->power != i)
{
prev = curr;
curr = curr->next;
}
if (curr->power == i)
{
curr->coeff = value;
}
else if (curr->next == nullptr && i == curr->power + 1)
{
curr->next = new Node; // Creates a node at the end of the list
curr = curr->next; // Points to that node
curr->next = nullptr; // Prevents it from going any further
curr->power = i;
curr->coeff = value;
}
else
{
prev->next = newNode;
newNode->next = curr;
}
}
else
{
curr->next = newNode;
curr = curr->next;
}
}
else
{
throw std::out_of_range("Index out of range");
}
}
It is a series of clear incorrect assumptions of how dynamic memory is managed in C++ that is getting you into heap-loads of trouble in this code. Were this not an academic exercise I would tell you simply to throw it all away and use:
std::map<size_t, double>
also known as: The Good Stuff. It would do literally everything you need this code to accomplish.
But this is academia. Like most things in academia they make you crawl through trenches before you learn how it should be. So, I will expose what is deficient in your code, but suffice it to say, once you learn all this you will strive not to have to do it in the first place by using tools already available to you.
In other words, unless someone said I had to do this with a hand-coded linked list implementation, I would use the above map instead. You can't (yet), but know it is there.
Your Code
You didn't include the definition of Node, but I can only assume it looks something like this:
struct Node
{
double coeff;
size_t power;
Node *next;
};
Whether this is nested within class Poly or not (and it likely should be if the latter) is likewise unclear. It isn't entirely relevant to the question, but mentioned here to attempt to drive home that, when asking a question on SO, provide enough info to minimize assumptions that may affect the answers your getting.
With that your code:
void Poly::setCoeff(double value, size_t i)
{
if (0 <= i) // NOTE: not needed, unsigned, will always be i >= 0
{
Node* prev = new Node(); // NOTE: wrong. leaks memory.
Node* curr = new Node(); // NOTE: same as above
Node* newNode = new Node(); // NOTE: **may** leak (see below)
newNode->coeff = value;
newNode->power = i;
curr = myHead;
if (curr != nullptr) // OK: check for null good
{
// NOTE: should be checking `curr`, not curr->next
while (curr->next != nullptr && curr->power != i)
{
prev = curr;
curr = curr->next;
}
// NOTE: should check curr for NULL first.
if (curr->power == i)
{
curr->coeff = value;
}
// NOTE: same here. also,
else if (curr->next == nullptr && i == curr->power + 1)
{
// NOTE: this code path will leak newNode allocated at the
// top of the function.
curr->next = new Node;
curr = curr->next;
curr->next = nullptr;
curr->power = i;
curr->coeff = value;
}
else
{
prev->next = newNode;
newNode->next = curr;
}
}
else
{ // NOTE: this is where your mainline fault is coming from. you
// just validated curr can be NULL here (and will be on initial)
curr->next = newNode;
curr = curr->next;
}
}
// NOTE: this can't happen, as i can never be less than zero
else
{
throw std::out_of_range("Index out of range");
}
}
The following are somewhat obvious.
Your memory management is not correct, and includes introducing memory leaks.
Your pointer management is likewise poor. Pointers are not like Java references, and nothing will get you in trouble faster in a C/C++ program than improper pointer management.
The algorithm doesn't maintain the mandate the list be ordered.
Changes to Your Code
The requirements for your code mandate an ordered list is maintained, yet your coefficient insertion algorithm makes no attempts at fulfilling that requirement. The setCoeff member is required to insert a new term if the matching exponent cannot be found, and if kept sorted, you'll know by proper enumeration whether that is the case by discovering (a) an exponent beyond yours, or (b) the end of the list, whichever happens first.
i is a size_t value, which means it is a magnitude for object counting. The standard mandates size_t is unsigned, which means it cannot be negative. This means checking for i >= 0 is useless. It will always be so.
A new node is allocated before know you need one. Remember, this is supposed to update an existing node if you find a matching exponent entry. Only if there were no match should a new node be required.
Your first-insert detection needs a complete redeux. It is guaranteed to invoke undefined behavior.
First make it easier on yourself. Provide a Node constructor that sets up a node via parameters so you can stop littering your code with that setup. In doing so, it becomes both easier to read and safer, since you initialize all member variables at construction.
struct Node
{
Node *next;
double coeff;
size_t power;
Node(double coeff_, size_t power_, Node *next_=nullptr)
: coeff(coeff_), power(power_), next(next_)
{}
};
With that, things will get considerably easier. The punch list above can be fulfilled with the following changes:
void Poly::setCoeff(double value, size_t i)
{
Node *prev = nullptr; // points to prior node
Node *curr = myHead; // points to current node
while (curr && curr->power < i)
{
prev = curr; // remember current node...
curr = curr->next; // ... then move to next node
}
// only allocate a new node if
// (a) we reached the end of the list (curr == NULL)
// (b) we reached a node with non match (will be larger exponent)
if (!curr || curr->power != i)
{
// **NOW** allocate the new node. we know we need one and we
// have a pretty solid idea where it goes.
Node *newNode = new Node(value, i, curr);
// if prev is set, then it means the new node goes somewhere
// *past* the head pointer otherwise it will become the new head.
if (prev)
prev->next = newNode;
else
myHead = newNode;
}
else
{ // found matching node
curr->coeff = value;
}
}
I sincerely hope it helps, and wish you the best of luck in trenching through the cruft before you get to The Good Stuff. Its worth it in the end.
I will follow up with the answer using a std::map (as WhozCraig's excellent answer mentions):
#include <map>
#include <iostream>
typedef std::map<size_t, double> Polynomial;
void AddCoefficientAndPower(Polynomial& poly, double coeff, size_t power)
{
// This does everything your assignment asked for, except for implementing
// all of that linked list stuff
poly[power] = coeff;
}
using namespace std;
int main()
{
Polynomial myPoly;
// add the coefficient and power
AddCoefficientAndPower(myPoly, 3, 1);
AddCoefficientAndPower(myPoly, 4, 2);
AddCoefficientAndPower(myPoly, 9, 0);
AddCoefficientAndPower(myPoly, 6, 3);
// This one will replace the previous (4,2)
AddCoefficientAndPower(myPoly, 3, 2);
// write out the coefficients followed by the power
Polynomial::iterator it = myPoly.begin();
while (it != myPoly.end())
{
cout << it->second << "^" << it->first << "\n";
++it;
}
}
Output:
9^0
3^1
3^2
6^3
Basically your entire assignment is a one line C++ statement in AddCoefficent that inserts an item in the map, and replaces an existing entry if one did exist.
Note -- no memory leaks, no calls to new, no crashes, etc.
Also, if your requirements were to also include any integral power value, then the above method works for negative, 0, and positive power values.

c++ Linked List with priority queue

I trying to code out the Linked List with priority queue and i encountered some problem.
I have about 7 priority from 1 the most to 7 the least important.
here's my current insert method.
void queue::addToQueueList(int newPriority, double newFare, int custID)
{
node* newnode= new node;
newnode->priority= newPriority;
newnode->fare = newFare;
newnode->cusID = custID;
newnode->next= NULL;
if (isempty())
{
front = back = newnode;
}
else
{
node* temp = front;
if(newnode->priority < temp->priority)
{
newnode->next = front;
front = newnode;
}
else
{
while(newnode->priority < temp->priority)
{
if(temp->next == NULL)
{
break;
temp = temp->next;
}
}
if(temp->next == NULL && newnode->priority < temp->priority)
{
back->next = newnode;
back = newnode;
}
else
{
newnode->next = temp->next;
temp->next = newnode;
}
}
}
}
Invoked as:
qList->addToQueueList(2, 488.88, A);
qList->addToQueueList(1, 388.88, B);
qList->addToQueueList(3, 488.88, C);
Expected result should be :
B, A, C
THe result shows :
B, C, A
Your making this considerably harder than it needs to be. Ultimately you need to walk the list, find the insertion point, remember how you arrived at that insertion point, and wire both your fore and aft pointers appropriately. Also a priority queue has no reason to keep a "back" pointer, so I'm not sure why you have one.
There are a number of ways to do this. First, to make the code cleaner to understand, providing a proper parameterized constructor for node is both trivial and helpful:
struct node
{
int priority;
double fare;
int cusID;
node *next;
node(int p, double f, int id, node *nxt = nullptr)
: priority(p), fare(f), cusID(id), next(nxt)
{
}
};
One you have that, you can go down the road you were apparently trying to navigate, using a pointer-value list walking approach. To do that you need to maintain a previous pointer:
void queue::addToQueueList(int newPriority, double newFare, int custID)
{
node* temp = front, *prev = NULL;
while (temp && temp->priority < newPriority)
{
prev = temp; // remember how we got here
temp = temp->next; // advance to next node
}
// create new node, linking to temp
node *newnode = new node(newPriority, newFair, custID, temp);
// link to previous node or assign as new head, whichever is needed
if (prev != nullptr)
prev->next = newnode;
else
head = newnode;
// though there is no need for a back pointer in a priority queue
// you had one none-the-less, so....
if (!temp)
back = newnode;
}
it is worth noting that this algorithm will insert new arrivals with similar priority at the head of that priority section of the list. I.e. the newest arrivals for a given priority are always at the forefront of that priority's position in the queue. If you want the oldest arrivals of a given priority to be "ahead" of their brethren, you simply need to change this:
while (temp && temp->priority < newPriority)
to this:
while (temp && temp->priority <= newPriority) // note < is now <=
Best of luck.
The comparison in your while loop is wrong. When inserting C newnode->priority == 3 and temp(B)->priority == 1. Thus the while loop is never entered.
Also, the temp = temp->next inside the while loop should be outside (after) the if statement. Otherwise this will be an infinite loop.
Assuming you are correcting these: you will always insert the new element after temp. Be aware of this in your fix of your comparisons. You are likely to add comparisons with temp->next->priority as well.
I agree with Joachim in the comments: step through the code with a debugger. Then you can see the values of the variables and which comparisons produce which results.