Different output while using node and node pointer in structure - c++

I am writing code to create a stack and know whether the stack is empty or not.
#include <stdio.h>
#include <stdlib.h>
struct stack
{
/* data */
int size;
int top;
int *arr;
};
// Functions
int isEmpty(struct stack ptr)
{
if (ptr.top == -1)
{
/* code */
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack ptr)
{
if (ptr.top == ptr.size - 1)
{
/* code */
return 1;
}
else
{
return 0;
}
}
int main()
{
struct stack s; // Stack is used as pointer for ease.
s.size = 80;
s.top = -1;
s.arr = (int *)malloc(s.size * sizeof(int));
// Pushing an element manually
s.arr[0] = 7;
s.top++;
if (isEmpty(s))
{
/* code */
printf("The stack is empty.\n");
}
else{
printf("The stack is not empty.\n");
}
if (isFull(s))
{
/* code */
printf("The stack is full.\n");
}
else{
printf("The stack is not full.\n");
}
return 0;
}
This code goes very well. But when I use Node *(pointer) for the stack, program doesn't execute completely.
#include <stdio.h>
#include <stdlib.h>
struct stack
{
/* data */
int size;
int top;
int *arr;
};
// Functions
int isEmpty(struct stack *ptr)
{
if (ptr->top == -1)
{
/* code */
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack *ptr)
{
if (ptr->top == ptr->size - 1)
{
/* code */
return 1;
}
else
{
return 0;
}
}
int main()
{
struct stack *s; // Stack is used as pointer for ease.
s->size = 8;
s->top = -1;
s->arr = (int *)malloc(s->size * sizeof(int));
// Pushing an element manually
// s->arr[0] = 7;
// s->top++;
if (isEmpty(s))
{
/* code */
printf("The stack is empty.");
}
else{
printf("The stack is not empty.");
}
return 0;
}
Sometimes the code doesn't even run. And.....
Sometimes this shows an error like this:
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe:
cannot open output file Creation.exe: Permission denied
collect2.exe: error: ld returned 1 exit status
Please help!!

The problem in the 2nd code snippet is that s is uninitialized meaning it is not pointing to any object and you're dereferencing it when you wrote s->size, s->top and s->arr, which leads to undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
For example, here the program doesn't crash but here it crashes.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
To solve this make sure that s points to a stack object before dereferencing it(s).
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

Related

Segmentation fault in C++ with std::cin while macro is defined

I am trying to solve a problem related to stack data structure, I have an implementation of a stack, and a main method that uses it, this is a for-learning question as i am a beginner, can you guys tell me, why i get this error?:
GDB trace:
Reading symbols from solution...done.
[New LWP 24202]
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 main () at solution.cc:70
70 cin >> N;
#0 main () at solution.cc:70
my code is the following:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX_SIZE 5000000
class Stack
{
private:
int A[MAX_SIZE]; // array to store the stack
int top; // variable to mark the top index of stack.
public:
// constructor
Stack()
{
top = -1; // for empty array, set top = -1
}
// Push operation to insert an element on top of stack.
void Push(int x)
{
if(top == MAX_SIZE -1) { // overflow case.
printf("Error: stack overflow\n");
return;
}
A[++top] = x;
}
// Pop operation to remove an element from top of stack.
void Pop()
{
if(top == -1) { // If stack is empty, pop should throw error.
printf("Error: No element to pop\n");
return;
}
top--;
}
// Top operation to return element at top of stack.
int Top()
{
return A[top];
}
// This function will return 1 (true) if stack is empty, 0 (false) otherwise
int IsEmpty()
{
if(top == -1) return 1;
return 0;
}
// ONLY FOR TESTING - NOT A VALID OPERATION WITH STACK
// This function is just to test the implementation of stack.
// This will print all the elements in the stack at any stage.
void Print() {
int i;
printf("Stack: ");
for(i = 0;i<=top;i++)
printf("%d ",A[i]);
printf("\n");
}
};
int main() {
int N;
cin >> N;
Stack S1;
Stack S2;
for(int i = 0; i < N; i++)
{
int q;
cin >> q;
if(q == 1)
{
int x;
cin >> x;
if(S1.IsEmpty() || S2.IsEmpty())
{
S1.Push(x);
S2.Push(x);
}
else
{
S1.Push(x);
if(x >= S2.Top()) S2.Push(x);
}
}
if(q==2)
{
if(S1.Top() == S2.Top())
{
S1.Pop();
S2.Pop();
}else
{
S1.Pop();
}
}
if(q==3)
{
cout << S2.Top() << endl;
}
}
return 0;
}
if i set MAX_SIZE variable to a lower number the code runs well, i want to know why is that the case, how std::cin and macros interact??, i am a beginner, sorry if this is a simple question it is the first time that i am asking in stackoverflow,
MAX_SIZE is far too big. MAX_SIZE determines the size of your Stack objects. As the total size of local variables in a function is limited to a few megabytes (depending on the platform), you simply exceed this size.
In your case you have two local Stack objects in main (S1and S2), each of them taking roughly 20 Mbytes (assuming sizeof int is 4).
This is totally unrelated to cin though.
Your Stack objects are allocated on the stack.
By default the stack is limited to something like 1-8 MB per thread depending on your platform.
Each of your stack objects takes up 20 MB so you are running out of stack space. To fix this change your code to:
std::unique_ptr<Stack> S1(new Stack());
std::unique_ptr<Stack> S2(new Stack());
This will allocate your objects on the heap which is only limited by the size of the available memory and swap space on your machine.

Member variable resetting back to 0

When running through the test the count variable from the class stack1 gets reset back to 0 when using its pop function. Strangely however, during the push loop, the count increases as intended but when pop occurs, the count gets reset back to 0 and subtracts into the negatives from there. Is there something I'm forgetting?
#include <iostream>
using namespace std;
class TheStack
{
public:
TheStack();
void push(int);
int pop();
bool isEmpty();
private:
const int MaxSize = 10;
int arr[10];
int count;
};
TheStack::TheStack()
{
count = 0;
}
void TheStack::push(int userInput)
{
if (count >= MaxSize)
{
cout << "Stack is full." << endl;
}
else
{
arr[count] = userInput;
count+=1;
}
}
int TheStack::pop()
{
if (isEmpty())
{
cout << "Stack is empty." << endl;
}
else
{
int temp = arr[count];
arr[count] = NULL;
count-=1;
return temp;
}
}
bool TheStack::isEmpty()
{
if (count == 0)
{
return true;
}
else
{
return false;
}
}
int main()
{
TheStack stack1;
if (stack1.isEmpty())
{
cout << "isEmpty() works" << endl;
}
stack1.pop();
for (int i = 0; i < 10; i++)
{
stack1.push(i);
}
stack1.push(0);
stack1.pop();
stack1.pop();
stack1.pop();
stack1.pop();
system("pause");
}
When you do push you first save the data into the array and then increment count. This means that in order to properly do pop you need to work in reverse: first decrement count and only then read data from the array.
But in the code you are doing it backwards. When the stack is full, count is at max value (10 in your case), and your arr[count] = NULL; writes beyond the array boundary. This causes undefined behavior and, in particular, destroys your count value. (This is why it suddenly becomes 0.)
Also:
arr[count] = NULL; makes no sense. NULL is supposed to be used in pointer contexts, not in integer contexts. This is not even guaranteed to compile.
What is the point of that anyway? Initially your array contains garbage above the current top of the stack. Why do you suddenly care to clean it up after doing pop?
Not all control paths of pop() return value. This is undefined behavior in itself.
const int MaxSize = 10; in the class definition is a C++11 feature. Since you are already using C++11, you can do the same for count. Just do int count = 0; right inside the class definition and you will not have to write the constructor explicitly.
Although in your implementation MaxSize would make more sense as a static const class member. In that case you'll also be able to declare your array as int arr[MaxSize];.
You must first decrease count and then access arr[count] in int TheStack::pop(). Now you get access above the last pushed element, event out of bound of array if the stack is full.

c++ code works properly but the process ends with termination instead return 0

i wrote a simple c++ code in codeblocks and i implemented stack and graph classes for that with dynamic memory allocation.
my code works properly and gives correct output but at the end it shows ***.exe has stopped working error and shows "Process terminated with status -1073741819" in build log.
i tried GNU gdb 6.8 debugger and it couldn't find any errors.
this problem was made after imlementing stack class, so this is my code if it can helps solving problem:
class stack
{
vertex* d;
int end;
public:
stack()
{
end=0;
d=NULL;
}
void create(int n)
{
d=new vertex[n];
}
vertex top()
{
return d[end];
}
void push(vertex y)
{
end++;
d[end]=y;
}
vertex pop()
{
end--;
return d[end+1];
}
~stack()
{
if (d!=NULL)
delete d;
}
};
vertex class is also declared before stack.
for some inputs, debugger says "Program received signal SIGSEGV, Segmentation fault."
edit: main asked:
int main()
{
G graf;
graf.get();
stack tree;
tree.create(graf.q()-1);
int q=0;
int i=0;
int u=0;
while (u<graf.q()-1)
{
tree.push(graf.u[i]);
if (graf.u[i].r[0]->flag > 0 && graf.u[i].r[1]->flag > 0 && u>=q)
tree.pop();
else
{
u++;
if (graf.u[i].r[0]->flag==0)
q++;
if (graf.u[i].r[1]->flag==0)
q++;
graf.u[i].r[0]->flag++;
graf.u[i].r[1]->flag++;
cout << tree.top().r[0]->name << " - " << tree.top().r[1]->name << '\n';
}
i++;
}
return 0;
}
i even tried adding a cout just before return 0 and my text printed.
Your code is wrong:
void push(vertex y)
{
end++;
d[end]=y;
}
Should be:
void push(vertex y)
{
d[end]=y;
end++;
}
Else, first pushed item goes to position 1instead of position 0.
Moreover, stack::top() returns next item, not last pushed:
vertex top()
{
return d[end];
}
should be:
vertex top()
{
return d[end-1];
}
I'm pretty sure you seg fault is due to unallocated memory being accessed, add assertions to have the program notify you when something gets wrong, like that:
class stack
{
vertex* d;
int cur;
int capacity;
public:
stack()
{
cur=0;
capacity=0;
d=NULL;
}
void create(int n)
{
assert( d == NULL );
capacity = n;
d=new vertex[n];
}
vertex top()
{
assert( cur != 0 );
return d[cur-1];
}
void push(vertex y)
{
cur++;
assert( cur < capacity );
d[cur]=y;
}
vertex pop()
{
assert( cur > 0 );
cur--;
return d[cur+1];
}
~stack()
{
if ( d != NULL )
delete [] d;
}
};
Then, run again, you'll see where you get an assertion.
Finally, check vertex copy constructor works fine, because pushing/poping does a lot of vertexcopy, if there's something wrong here, it could cause seg fault.

pointer being freed was not allocated error?

I have seen many posts for this error. But I'm not reserving memory dynamically or doing anything in destructor:
This program is SSJF algorithm for selecting cylinder in operating system.
I have a simple class called IO:
class IO
{
public:
IO();
IO(int,int);
void setIO(int,int);
~IO();
int trackNo;
int arrival;
int start;
int end;
bool finished;
};
Here is the implementation of the class::
IO::IO(int arr, int tNum)
{
this->arrival = arr;
this->trackNo = tNum;
this->start = 0;
this->end = 0;
}
IO::IO()
{
}
IO::~IO()
{
}
void IO::setIO(int t1, int t2)
{
this->trackNo = t1;
this->arrival = t2;
}
And finally here is part of main program:
list<IO> myList;
....
myList.push_back(tmpIO); //Add to the list
...
list<IO> wt_list;
And later I'm trying to do some operations. I have deleted some of the part which is not related.
//list<IO>::iterator itMin;
while(myList.size()>0)
{
//If it is the first input just get it
if(f)
{
IO selected = myList.front();
curr_time += selected.arrival + selected.trackNo;
f=false;
cout << selected.arrival<<endl;
lastPos = selected.trackNo;
myList.pop_front();
}
//Check if there is any item to add to queue
while(myList.front().arrival < curr_time)
{
wt_list.push_back(myList.front());
myList.pop_front(); //Error is coming from this line
}
while(wt_list.size()>0)
{
}
Error message:
malloc: * error for object 0x10f68b3e0: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
Anyone can help me and explain why I get this error and how can I skip it?
The simplest code I can come up with to reproduce this error looks like this:
#include <list>
int main()
{
std::list<int> mylist;
mylist.pop_front();
}
I can prevent the error by doing:
#include <list>
int main()
{
std::list<int> mylist;
if (!mylist.empty())
{
mylist.pop_front();
}
}
You're calling:
myList.pop_front();
...within a while-loop, which in turn is within a while-loop that also calls myList.pop_front().
I can only suggest that you debug your code to see how many times pop_front() is invoked for mylist. My money is on it being more than mylist.size() times, hence my question in the comments (with new emphasis):
How many items are in myList when the error is thrown?
Perhaps the simplest fix will be to replace...
//Check if there is any item to add to queue
while(myList.front().arrival < curr_time)
{
wt_list.push_back(myList.front());
myList.pop_front(); //Error is coming from this line
}
while(wt_list.size()>0)
{
}
...with...
while (!mylist.empty() && myList.front().arrival < curr_time)
{
wt_list.push_back(myList.front());
myList.pop_front();
}
while (!wt_list.empty())
{
}
...but it's hard to tell from the snippet you've provided.

How can I prevent segmentation faults in my program?

I have a C assignment. It is a lot longer than the code shown below, and we are given the function prototypes and instructions only. I have done my best at writing code, but I am stuck with segmentation faults. When I compile and run the program below on Linux, at "735 NaN" it will terminate, indicating a segfault occurred. Why? What am I doing wrong? Basically, the program does not let me access table->list_array[735]->value and table->list_array[735]->key. This is of course the first segfault. There might be more following index 735.
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node list_node_t;
struct list_node
{
char *key;
int value;
list_node_t *next;
};
typedef struct count_table count_table_t;
struct count_table {
int size;
list_node_t **list_array;
};
count_table_t* table_allocate(int size)
{
count_table_t *ptr = malloc(sizeof(count_table_t));
ptr->size = size;
list_node_t *nodes[size];
int k;
for(k=0; k<size; k++){
nodes[k] = NULL;
}
ptr->list_array = nodes;
return ptr;
}
void table_addvalue(count_table_t *table)
{
int i;
for(i=0; i<table->size; i++)
{
table->list_array[i] = malloc(sizeof(list_node_t));
table->list_array[i]->value = i;
table->list_array[i]->key = "NaN";
table->list_array[i]->next = NULL;
}
}
int main()
{
count_table_t *table = table_allocate(1000);
table_addvalue(table);
int i;
for(i=0; i<table->size; i++)
printf("%d %s\n", table->list_array[i]->value, table->list_array[i]->key);
return 0;
}
You're point ptr->list_array at a local variable (nodes) in table_allocate, which goes away when that function returns, leaving a dangling pointer. You probably want
list_node_t **nodes = malloc(size * sizeof(list_node_t *));
I recommend the routine use of valgrind(1) to prevent such problems from occurring.