inconsistent segmentation faults during runtime - c++

I'm currently taking a jab at Project Euler #9 and am encountering segmentation faults. These segfaults only occur with every 3rd-4th time I run the program. Could someone explain why this might be the case and more importantly, why it doesn't segfault (or work) every time instead?
I've pinpointed the segfault to the beginning of the 2nd while loop but still can't determine the root cause.
#include <iostream>
#include "LinkedList.h"
using namespace std;
int main(){
int square, sum, answer = -1;
int start = 1;
LinkedList tripletChoices;
while (square<=1000){
//create new node
node * factor = new node;
factor->root = start;
square = start*start;
factor->square = square;
//insert into list
if (square<=1000) tripletChoices.insertNode(factor);
start++;
}
node * a_factor = tripletChoices.head;
/** segfaults just after this ***********************/
cout<<"before segfault" << endl;
while(a_factor->next!=NULL){
cout<<"after segfault" << endl;
node * b_factor = a_factor->next;
while(b_factor->next!=NULL){
sum = a_factor->square + b_factor->square;
cout<<"A: " << a_factor->square << " B: " << b_factor->square<< " sum:" << sum <<endl;
node * c_factor = tripletChoices.head;
while(c_factor->next!=NULL){
if (sum == c_factor->square){
if ((a_factor->root + b_factor->root + c_factor->root)==1000){
answer = a_factor->root * b_factor->root * c_factor->root;
break;
}
}
c_factor = c_factor->next;
}
b_factor = b_factor->next;
}
a_factor = a_factor->next;
}
cout<<"Answer: " << answer << endl;
}
the rest of my code (if relevant):
LinkedList.h
#ifndef LinkedList_h
#define LinkedList_h
struct node{
int root;
int square;
node *next;
};
class LinkedList{
public:
node * head;
int listLength;
//default constructor creates head node
LinkedList();
//setter method
bool insertNode(node * newNode);
//destructor de-allocates memory used by the list
~LinkedList();
};
#endif
LinkedList.cpp
#include "LinkedList.h"
#include <iostream>
//Default Constructor - initilizes list with head node
LinkedList::LinkedList(){
head = NULL;
listLength = 0;
}
// setter method for inserting a new node
// inserts new node at the head of the list
bool LinkedList::insertNode(node * newNode){
newNode->next = head;
head = newNode;
listLength++;
return true;
}
//Destructor de-allocates memory used by list
LinkedList::~LinkedList(){
node * p = head;
node * q = head;
while(q){
p = q;
q = p->next;
if (q) delete p;
}
}

Undefined behavior because of accessing uninitialized local variable
You are accessing uninitialized variable square before entering while loop, so it may or may not enter the while loop. So tripletChoices.head may or may not be non-null as you can't be sure if there would have happened any insertion or not!
Thus, dereferencing the null valued a_factor in while(a_factor->next!=NULL) would cause the SegFault.

Related

Getting Segmentation fault while traversing linked list

I've simple C++ program to traverse a linked list.
It runs perfectly in ideone .
When I run this in my mac terminal it throws segmentation fault.
When I uncomment //printf("Node"); line from traverse function it runs perfectly. I'm not able to understand this behavior.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef struct node {
int data;
struct node *next;
} Node;
void traverseLinkedList(Node *start) {
while(start) {
//printf("Node");
cout << start->data << "->";
start = start->next;
}
cout << "NULL" << endl;
}
int main() {
Node *start = (Node*) malloc(sizeof(Node));
Node *a = (Node*) malloc(sizeof(Node));
Node *b = (Node*) malloc(sizeof(Node));
start->data = 0;
a->data = 1;
b->data = 2;
start->next = a;
a->next = b;
traverseLinkedList(start);
traverseLinkedList(a);
traverseLinkedList(b);
return 0;
}
You forgot this statement
b->next = nullptr;
Otherwise the program has undefined behavior due to the condition in this while statement in the function traverseLinkedList
while(start)
Take into account that in C++ you should use the operator new instead of the C function malloc.
For example
Node *b = new Node { 3, nullptr };
Node *a = new Node { 2, b };
Node *start = new Node { 1, a };
And you should free the allocated memory before exiting the program.

C++ Linked List Node with class

Specifically, the goal here is to create a linked structure that has some number of nodes, between 5 and 2 million. Don’t worry that this number is large or that values may wrap around past the max size of integer. If you have created your linked structure correctly, a modern computer can breeze through this code very quickly. Notice that the comments describe exactly how this main should work. Here are the highlights:
Create three loops
The first loop creates the linked structure, hooking together the “next” fields of each node and giving each node an integer value between 0 and the randomly chosen size.
The second loop adds up all of the nodes and counts them. Counting the nodes in this case should be used only as check to make sure you are not missing one.
The third loop traverses all nodes again, this time deleting them.
Node.h
class Node {
public:
Node();
Node(const Node& orig);
virtual ~Node();
bool hasNext();
Node* getNext();
void setNext(Node* newNext);
int getValue();
void setValue(int val);
private:
Node* next;
int value;
};
#endif
Node.cpp
include "Node.h"
include <iostream>
Node::Node() {
next = NULL;
}
Node::Node(const Node& orig) {
next = orig.next;
value = orig.value;
}
Node::~Node() {
}
bool Node::hasNext(){
if (next != NULL)
return true;
else
return false;
}
Node* Node::getNext(){
return next;
}
void Node::setNext(Node* newNext){
if(newNext == NULL)
next = NULL;
else
next = newNext->next;
}
int Node::getValue(){
return value;
}
void Node::setValue(int val){
value = val;
}
main.cpp
include <cstdlib>
include <iostream>
include "Node.h"
include <time.h>
using namespace std;
int main(int argc, char** argv) {
//This is the node that starts it all
Node *tail;
Node* head = new Node();
//select a random number between 5 and 2,000,000
srand(time(NULL));
int size = (rand() % 2000000) + 5;
int total = 0;
int counter = 0;
//print out the size of the list that will be created/destroyed
cout << "The total size is: " << size << endl;
head->setValue(0);
tail = head;
Node *newNode = new Node;
for (int i = 1; i < size; i++){
Node *newNode = new Node;
newNode->setValue(i);
newNode->setNext(NULL);
tail->setNext(newNode);
tail = newNode;
}
//Create a list that counts from 0 to 2,000,000
//Link all of the nodes together
//A for loop is easiest here
cout << head->getNext()->getValue();
Node* current = head;
while (current != NULL){
counter += current->getValue();
cout << current->getValue();
current = current->getNext();
total++;
}
//Traverse the list you created and add up all of the values
//Use a while loop
//output the number of nodes. In addition, print out the sum
//of all of the values of the nodes.
cout << "Tracked " << total << " nodes, with a total count of " << counter << endl;
//Now loop through your linked structure a third time and
//delete all of the nodes
//Again, I require you use a while loop
cout << "Deleted " << total << " nodes. We're done!" << endl;
return 0;
}
It is printing out the total size then...
I am getting a Seg fault:11.
I am also missing some parts in the main, I am confused on how to write these as well.
it should be next = newNext; instead of next = newNext->next;
void Node::setNext(Node* newNext){
if(newNext == NULL)
next = NULL;
else
next = newNext;
}
First of all, avoid using getter functions in your Abstract Data Type. Those should be reserved for your client test application; keep them out of your ADT. Instead, pass any values in as parameters as re: the prototype. Second, avoid void returning methods in your classes. Rather, return a bool or int. Zero or false for error, and true or some non-zero integer for your success message.
That aside, I was looking up ways to use classes to build nodes, and your post came up. Interesting start. We'll see where we go with this.
Ciao,
Lewsutt

Why does this program break with delete command?

I want to delete a certain element from a linked list (it's a list of numbers).
When i find the right number, i check if the previous element is NULL. If it is, it's the head of the list, and i just move that pointer, and if it isn't i re-link elements, so that the previous element points to the next element of the element to be deleted.
Now, this works fine, unless i uncoment the following command:
delete old;
Now, old is a pointer that points to the element that needs to be deleted.
I want to delete the element, not just re-link the list.
// zag.h - header file
#ifndef _zag_h_
#define _zag_h_
#include <iostream>
using namespace std;
struct Elem {
int n;
Elem* next;
Elem(int bbr,Elem* nex = NULL){n = bbr; next = nex;}
~Elem(){delete next;}
};
class Lista {
Elem* head;
public:
Lista(){
head=NULL;
}
~Lista(){
}
void put(int broj){
Elem* temp = new Elem(broj);
Elem* n0 = NULL;
Elem* n1 = head;
while(n1!=NULL && temp->n >= n1->n){
n0 = n1;
n1 = n1->next;
}
if(n0 == NULL){
temp->next=head;
head = temp;
}
else {
n0->next = temp;
temp->next = n1;
//if(n1==NULL)tail=temp;
}
//cout << head->n << endl;
}
void remove(int num){
Elem* n1 = head;
Elem* n0 = NULL;
while(n1!=NULL && n1->n!= num){
n0 = n1;
n1 = n1->next;
}
if(n0 == NULL){
Elem* old = n1;
head = head->next;
n1 = n1->next;
delete old;
}
else {
Elem* old = n1;
n1 = n1->next;
n0->next = n1;
cout << old->n;
delete(old);
}
}//remove
void write(){
Elem* temp = head;
while(temp){
cout << temp->n << " ";
temp = temp->next;
}
cout<<endl;
} //ispisi
};
#endif
// main.cpp file
#include "zaglavlje.h"
#include <iostream>
using namespace std;
void main(){
cout << "Welcome " << endl;
Lista* l = new Lista();
l->put(4);
l->put(2);
l->put(8);
l->put(7);
l->put(6);
l->put(9);
l->put(11);
l->put(15);
l->put(17);
l->put(2);
l->put(1);
l->write();
l->remove(11);
//l->remove(2);
//l->remove(2);
//l->remove(11);
//l->remove(15);
cout << "ispisujemo elemente liste nakon brisanja" << endl;
l->ispisi();
}
So, i insert some elements in the list, write the list elements (which all seems to work fine), and then i call a function to remove one element. After that, when i try to write the list (to check if the element is really removed) i get the following error:
An unhandled win32 exception occurred in test.exe
and the debugger points the line
cout << temp->n << " ";
in the write function.
Without calling the delete old command it all works fine.
When your list is empty, you are attempting to access the "first" element anyway:
if (n0 == NULL && n1 == NULL)
{
// empty list, do nothing
}
else if (n0 == NULL && n1 != NULL)
{
Elem* old = n1;
head = head->next;
n1 = n1->next;
delete old;
}
else
{
Elem* old = n1;
n1 = n1->next;
n0->next = n1;
delete old;
}
When you remove the delete's in your current code, you are keeping the memory allocated, so you won't get an access violation when you access it incorrectly. When you add them back in, you are accessing memory that is no longer allocated when the list is empty.
This will also be a problem when you first run the program is head is not initialized.

Linked Lists Class

Okay I know this is a ridiculously easy question, but for some reason I cannot get a linked list to work. It may just be because I am really tired, because I've done them a million times before. Boiled my program down to the simplest possible implementation, still not working.
Very basic implementation, just make a LL of integers, something I have done a million times before but for whatever reason it's never progressing past head.
main.cpp
#include <iostream>
#include "ll.h"
using namespace std;
int main()
{
int x;
list ll;
int i =0;
while(i == 0)
{
cout << "Enter a value to add to the LL ";
cin >> x;
ll.add(x);
ll.display();
}
return 0;
}
ll.h
struct node
{
int val;
node * next;
};
class list
{
public:
list();
void add(int);
void display();
node * head;
};
ll.cpp
#include <iostream>
#include "ll.h"
using namespace std;
list::list()
{
head = NULL;
}
void list::add(int x)
{
if(!head)
{
cout << "First " << endl;
head = new node;
head->val = x;
head->next = NULL;
}
else
{
node * current = head;
while (current)
current = current->next;
current = new node;
current->val = x;
current->next = NULL;
}
}
void list::display()
{
node * current = head;
while(current)
{
cout << current->val << endl;
current = current->next;
}
}
It seems you want to append to the list. In this case, you loop condition shouldn't be
while (current)
but
while (current->next)
making sure is initially non-NULL (which you do with your check for the `head).
Actually, the logic for setting up the new node is also not quite right. You probably want to have the second branch of add() look something like this:
while (current->next) {
current = current->next;
}
current->next = new node(x);
... with a suitable constructor of node:
node::node(int x): val(x), next() {}
In addition to Dietmar's answer, you have an improper while loop:
while ( i == 0 ) {
...
}
In the body of the for loop, i is never changed, causing it to loop indefinitely. I'm not entirely sure what you want to use i for though.

Attempting to create a pointer to previous object inside object

I'm attempting to create a vector of pointers to Nodes, where each node stores a pointer to the previous Node in the list.
I made a small test program to see if I could access a variable gscore in the previous object to the one I call.
#include <iostream>
#include <vector>
using namespace std;
struct Node
{
Node(int gscore1)
{
gscore = gscore1;
}
Node *previous;
int gscore;
};
int main()
{
std::vector<Node*> nodeVec;
Node *tempnode;
tempnode = new Node(10);
Node *tempnode2;
tempnode = new Node(11);
nodeVec.push_back(tempnode);
nodeVec.push_back(tempnode2);
nodeVec[1]->previous = tempnode;
cout << nodeVec[1]->previous->gscore << endl;
return 0;
}
However this results in a crash. What is the correct way to do this?
You never initialize tempnode2. You initialize tempnode twice.
int main()
{
std::vector<Node*> nodeVec;
Node *tempnode;
tempnode = new Node(10);
Node *tempnode2;
tempnode2 = new Node(11); // <<---- HERE
nodeVec.push_back(tempnode);
nodeVec.push_back(tempnode2);
nodeVec[1]->previous = tempnode;
cout << nodeVec[1]->previous->gscore << endl;
return 0;
}
Looks like a typing error. The third line in main() should be tempnode2 not tempnode.