Hey guys I'm trying to run this code but I get segmentation fault when the compiler gets to the class functions.
This is the main function:
int main (int argc, char* argv[]){
cout<<"\t1.Add Program\n";
cout<<"\t2.Kill Program\n";
cout<<"\t3.Fragmentation\n";
cout<<"\t4.Print Memory\n";
cout<<"\t5.Exit"<<endl;
LinkedList Memory;
Memory.createMemory(); (I get the segmentation error on this line)
int choice;
cin>>choice;
cout<<"choice - "<<choice<<endl;
if (choice==1){
string programName;
cin>>programName;
cout<<"Program name - "<<programName<<endl;
int size;
cin>>size;
cout<<"Program size (KB) - "<<size<<endl;
int numpages;
if (size%4==0) numpages=size/4;
if (size%4!=0) numpages=size/4+1;
Memory.addProgram(numpages, programName);
return 0;
}
This is the class
class LinkedList{
private:
struct node{
string name;
node *next;
};
public:
void createMemory();
void addProgram(int val, string s);
void killProgram(string s1);
void print();
void fragmentation();
LinkedList(){head=NULL;};
};
And these are two of the class functions
void LinkedList::createMemory(){
int i=0;
node* temp;
temp = new node;
while(i<32){
temp->name="Free";
temp=temp->next;
i++;
}
};
void LinkedList::addProgram(int val, string s){
int i=0;
node* temp;
temp=new node;
while(temp->name!="Free")
temp=temp->next;
while(temp->name=="Free"){
while (i<val){
temp->name=s;
temp=temp->next;
i++;
}
}
cout<<"Program "<<s<<" added successfully: "<<val<<" page(s) used."<<endl;
};
The other functions in the class are similar to these two so they're all gonna have the same error.
The main function runs correctly, but when I call the class functions in the main i get the segmentation fault.
while(i<32){
temp->name="Free";
temp=temp->next;
i++;
}
In this snippet, you use null or uninitialized temp->next
Maybe there are more subtle errors in your code. Use a debugger.
Tip always to keep in keep in mind: in constructor initialize all members, not only selected.
In my code, I use constructors for struct too (some people advice otherwise)
In LinkedList::createMemory and LinkedList::addProgram, you are creating a new node in the scope of the function but you are not assigning such new node to a class variable. Therefore, when you exit your function, the pointer to the resource you created is lost and:
1) you leaked memory because you haven't called delete on the pointer
2) your class doesn't have any nodes
add a
node *_root;
variable to your LinkedList class and assign to it.
Now with this being said here's a couple of tips:
Don't use new like that, it is very easy to leak memory. Use std::unique_ptr so that resources are automatically cleared.
Use std::list if you want to have a LinkedList.
'createMemory()' Method that initializes the List got problem with memory allocation. Only the first node got memory allocated. You are re-assigning 'temp' with 'temp->next' which does not have memory allocated to it and accessing 'temp->name' which would cause the 'Segmentation fault'. If you are creating multiple nodes in an iterative fashion, you must allocate memory for each of the nodes in the loop. Use this stanford link as a reference to learn how to initialize Linked List: http://cslibrary.stanford.edu/103/LinkedListBasics.pdf
Related
whenever we are creating new node is it manadatory to make pointer to newnode first and allocate memory dynamically to it why can't we have normal variable of node class type !
so,what's wrong with normal variable of node type insted of having pointer to node type
CODE:
//creation of linked list
#include <iostream>
using namespace std;
class node{
public:
int data;
node* next;
};
class linked_list{
public:
node* head;
linked_list(){
head=NULL;
}
void add_node(int data);
void display_ll();
};
void linked_list :: add_node(int data){
node newnode; //HERE IN THIS LINE I KNOW IT SHOULD BE LIKE node* newnode;
if (head==NULL){ // AND DMA THAT NODE , WORKING FINE BUT WHAT'S WRONG WITH ACTUAL CODE
newnode.data=data;
newnode.next=NULL;
head=&newnode;
}
else{
node* temp=head;
newnode.data=data;
newnode.next=NULL;
while(temp->next!=NULL){
temp=temp->next;
}
temp->next=&newnode;
}
}
void linked_list :: display_ll(){
node* temp=head;
while (temp!=NULL)
{
cout<<temp->data<<" ";
temp=temp->next;
}
}
int main(){
linked_list ll;
ll.add_node(6);
ll.add_node(3);
ll.add_node(9);
ll.add_node(3);
ll.display_ll();
}
If you declare newnode as node newnode; within your method, then the object's memory is allocated on the stack, and its life time is local to the execution context of the method: when the function returns, that memory is freed.
That becomes a problem, because after the first call (ll.add_node(6)), head will reference that freed memory. Then ll.add_node(3) will allocate again memory, which could well be the same memory on the stack, and so you'll actually overwrite the first node's data, and temp->next=&newnode will make a bad reference. This will happen also with the other ll.add_node calls. The list is thus corrupted.
When you finally call ll.display_ll(), its temp will point to freed memory and so will temp->next, leading to undefined behaviour, unexpected output and potentially to an exception.
So, the rule is as follows:
If your function creates a reference to the object that will remain accessible after the function has returned, then you must allocate that memory dynamically (using a pointer). If on the other hand the object is only relevant during the execution of the function, and can be discarded when the function returns (without any reference to it), then it is not needed to use a pointer.
So lately I've been learning C++, and I am studying Linkedlist now.
I am wondering why don't we create Nodes with an array, let's say:
#include <iostream>
using namespace std;
struct Node {
int data = 0; //data
Node* next = nullptr; //next node in the linked list;
};
void deallocateLinkedList(Node* n)
{
if (n == nullptr) // An empty list; nothing to delete
return;
else{
deallocateLinkedList(n->next);
delete n;
n = nullptr;
}
}
int main()
{
int k;
cout<<"enter k as number of nodes"<<endl;
cin>>k;
Node* n = new Node [k]; //creates dynamic array;
for(int i =0;i<k;i++)
{
if (i==k-1)
{
n[i].data=i;
n[i].next=nullptr;
}
else
{
n[i].data=i;
n[i].next = &n[i+1];
}
}
deallocateLinkedList(n); //pointer points to the first node;
cout<<"programmed finished"<<endl; //indicates successful running
return 0;
}
In this case, the Nodes are linked and also put into an array;
However, the deallocate programme doesn't run completely and exit without error
Is there any problem with this style of creating Linked List or just the deallocation problem?
What If I Put All Nodes of LinkedList into an Array?
Then that's where the nodes are.
However, the deallocate programme doesn't run completely and exit without error
Is there any problem with this
Yes, there is a problem.
The problem is that you may only pass a pointer to delete if you got the pointer from new (and it must be deleted at most once, and if you created an array, then you must use delete[]).
When you do delete n;, you'll find that you never assigned any of n->next (which will be the n in the recursive call) to have a pointer value that was returned from new. As a consequence, the behaviour of the program is undefined.
If you allocate objects like this:
Node* n = new Node [k];
then you must deallocate like this:
delete[] n;
I am newbie in C++. The interviewer said it's bad practice to create an object within a function. Is it so?
#include <iostream.h>
class linkedlist {
int value;
linkedlist *next;
static linkedlist *p=NULL;
void insert(int data) {
linkedlist node;
node.value=data;
node.next=NULL;
if(p==NULL)
p=node;
else {
p->next=node;
p=p->next;
}
}
}
int main() {
linkedlist h;
h.insert(10);
h.insert(20);
return 0;
}
The problem is "lifetime"; the node you created lives only in the stack frame of the function and when the function terminates its memory is reclaimed. The static pointer p however will still link it and this will lead to "undefined behavior" when someone later accesses the linked list.
Using local objects is not bad in general, it's only bad if you expect them to survive the end of the function, because they don't.
You should allocate long-living objects the object on the free store, by using new.
I've just started learning C and am fairly a beginner.
Today in school we learned linked list and I was able to put up a code...which thankfully is running without errors.
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
}*head;//*temp;
void create(struct node **h,int num)
{
int i;
struct node *temp=*h;
for(i=0;;i++)
{
if(i>=num)
break;
temp->data=i;
temp->next=malloc(sizeof(struct node));
temp=temp->next;
}
temp->next=NULL;
}
void display(struct node **h)
{
struct node *temp=*h;
while(temp->next!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
printf("\b\b \b\b");
}
void append_end(struct node **h,int val)
{
struct node *temp=*h,*temp1;
//printf("'%d'",val);
while(temp->next!=NULL)
temp=temp->next;
temp1=malloc(sizeof(struct node));
temp1->data=val;
temp1->next=NULL;
temp->next=temp1;
}
void free_list(struct node **h)
{
struct node *temp=*h,*tail;
while(temp->next!=NULL)
{
tail=temp;
temp=temp->next;
free(tail);
}
h=NULL;
}
int main()
{
head=malloc(sizeof(struct node));
int i,num;
scanf("%d",&num);
create(&head,num);
//display(&head);
append_end(&head,5);
append_end(&head,6);
display(&head);
/*temp=head;
while(temp->next!=NULL)
temp=temp->next;
printf("%d",temp->data);*/
free_list(&head);
return 0;
}
The expected output should be
0->1->2->3->5->6
for input of 4
But instead I'm getting
0->1->2->3->(some garbage value)->5
I'll be glad if someone could point out my error(s), and/or link to any article that might help me in understanding the topic clearly.
Thanks in advance.
I've refactored your code. You can see it here: http://ideone.com/nZ55i
Your code was ugly, so I tweaked it into my own style. I suggest you find a style you like, that's easy for you to read.
Moved declaration of head into main method (used to be a global variable)
Functions that took pointer-to-pointer types for no reason have been modified to take pointers.
You used malloc(sizeof(struct node)) in at least 3 places, so I just up and made a function that does it for you.
Added a typedef to the declaration of the node struct, you can declare instances of it now with just node derp;
create function uses a for loop with an empty condition and a break, refactored to use a proper for loop with no break
The garbage value was caused by a bug in your create function that prevented it from writing the value to the last node it created. To fix it, I moved stuff around so it always assigns the data field but doesn't allocate a new node if it's at the end
Failure to write the last item in the list was caused by a bug in the display function that caused it to terminate before displaying the last node.
If this is a homework question and you turn in my code, I will find you, drive to your house, and shoot a rotten potato through your bedroom window with a cannon.
Okay, I started to put this in the comments, but putting code in comments will get brickbats :). This is not tested, and there are myriad ways to approach it (given I've diagnosed the problem correctly :) ), but one way that might work to fix your create method is offered as follows: (Note that I've simplified your loop, just using the normal termination condition for the 'for' loop construct, and eliminated the 'if..break' within the loop as its no longer needed. The "->next" member will always be initialized to a new member if there's one left to create, otherwise its NULL, so we don't need the ending assignment:
void create(struct node **h,int num)
{
int i;
struct node *temp=*h;
for(i=0;i<num;i++)
{
temp->data=i;
if (i==(num-1))
temp->next=NULL;
else
temp->next=malloc(sizeof(struct node));
temp=temp->next;
}
}
class Node{
private:
string name;
Node** adjacent;
int adjNum;
public:
Node();
Node(string, int adj_num);
Node(const Node &);
bool addAdjacent(const Node &);
Node** getAdjacents();
string getName();
~Node();
};
bool Node::addAdjacent(const Node &anode){
Node** temp;
temp= new Node*[adjNum+1];
for(int i=0;i<adjNum+1;i++)
temp[i]=adjacent[i];
temp[adjNum]=const_cast<Node *>(&anode);
delete[] adjacent;
adjacent=new Node*[adjNum+1];
adjacent=temp;
delete[] temp;
adjNum++;
return true;
}
int main()
{
Node node1("A",0);
Node node2("B",0);
node1.getName();
node1.addAdjacent(node2);
system("PAUSE");
return 0;
}
when the program comes to this part:
for(int i=0;i<adjNum+1;i++)
temp[i]=adjacent[i];
it says Access violation reading location 0xcccccccc. The class must allocate the memory fore adjacent, but I think it didn't how can I solve this problem?
adjacent=new Node*[adjNum+1];
adjacent=temp;
delete[] temp;
This looks like a bug. You probably meant to write:
adjacent = temp;
and that's it.
Also, I think the problem lies with
for(int i=0;i<adjNum+1;i++)
You're copying adjNum+1 elements, even though (I assume) adjacent only contains adjNum elements. Remove the +1 from the for loop.
Besides the issues strager mentioned, you might be missing initialization for adjacent, e.g. like this:
Node::Node(std::string name, unsigned adj_num)
: name(name)
, adjacent((adj_num > 0) ? new Node*[adj_num] : 0)
, adjNum(adj_num)
{}
Note the unsigned parameter, a negative adj_num is most likely meaningless in this context.
If you don't initialize adjacent, it contains some garbage value and dereferencing it or passing it to delete[] leads to undefined behaviour.