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

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.

Related

Different output while using node and node pointer in structure

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.

Stack Program in C++

I want to implement a code in my program where it guesses whether or not the given series of operations and corresponding return values from an input file are operating as a stack. In other words, the output is fully determined by the input file.
The text file (StackTest.txt):
4
INSERT 2
INSERT 1
REMOVE 1
REMOVE 2
6
INSERT 5
INSERT 10
INSERT 12
REMOVE 10
REMOVE 5
REMOVE 12
2
INSERT 8
REMOVE 8
Expected Output(from input file):
stack
not stack
stack
However, I'm stuck on how to implement this feature into my current code.
If anyone can help me out on how to achieve the expected output above or give me some hints, I would really appreciate it!
Code in progress...
#include <iostream>
#include <fstream>
#include <string>
#include <stack>
using namespace std;
// Function to check validity of stack sequence
bool validStackSeq(string input, int len)
{
// maintain count of popped elements
int j = 0;
// an empty stack
stack <int> s;
for(int i = 0; i < len; i++)
{
s.push(input[i]);
// check if appended value is next to be popped out
while (!s.empty() && j < len && s.top() == input[j])
{
s.pop();
j++;
}
}
return j == len;
}
int main()
{
ifstream inFile;
string data;
string command;
int num;
inFile.open("StackTest.txt");
//cout << "Reading file..." << endl;
stack <int> s;
while(getline(inFile, data))
{
if(command == "INSERT")
{
s.push(num);
}
else if(command == "REMOVE")
{
s.pop();
}
num = sizeof(data)/sizeof(data[0]);
cout << (validStackSeq(data, num) ? "Stack" : "Not Stack") << endl;
}
inFile.close();
}
Current Output
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack
Stack Validation Program (without input file)
#include <iostream>
#include <stack>
using namespace std;
bool validStackSeq(int pushed[], int popped[], int len)
{
int j = 0;
stack <int> pt;
for(int i = 0; i < len; i++)
{
pt.push(pushed[i]);
while (!pt.empty() && j < len && pt.top() == popped[j])
{
pt.pop();
j++;
}
}
return j == len;
}
// Driver code
int main()
{
int pushed[] = {2, 1};
int popped[] = {1, 2};
int len = sizeof(pushed)/sizeof(pushed[0]);
int pushed1[] = {5, 10, 12};
int popped1[] = {12, 5, 10};
int len1 = sizeof(pushed1)/sizeof(pushed1[0]);
int pushed2[] = {8};
int popped2[] = {8};
int len2 = sizeof(pushed2)/sizeof(pushed2[0]);
int pushed3[] = {1, 4};
int popped3[] = {4};
int len3 = sizeof(pushed3)/sizeof(pushed3[0]);
cout << (validStackSeq(pushed, popped, len) ? "Stack" : "Not Stack") << endl;
cout << (validStackSeq(pushed1, popped1, len1) ? "Stack" : "Not Stack") << endl;
cout << (validStackSeq(pushed2, popped2, len2) ? "Stack" : "Not Stack") << endl;
cout << (validStackSeq(pushed3, popped3, len3) ? "Stack" : "Not Stack") << endl;
return 0;
}
Perform the INSERT and REMOVE operations as specified in the text file. The result is 'stack' if all remove operations are possible (do not occur when the stack is empty) and the operand of each remove operation equals the actual value poped from your stack.
UPDATED 2020-02-29
You cannot create two separate arrays for INSERT and REMOVE operations and process them independently, because the result depends on how the operations are interleaved. For example
INSERT 1
INSERT 2
REMOVE 2
REMOVE 1
should result in stack, but if we move one REMOVE operation up:
INSERT 1
REMOVE 2
INSERT 2
REMOVE 1
the result will become not stack. It means that you need to process the operations in exactly same order as they appear in the file.
The general structure of the code:
ifstream inFile;
inFile.open("StackTest.txt");
int num;
while (inFile >> num) { // Read number of INSERT/REMOVE in each test set
stack<int> s;
bool isStack = true;
for (int i = 0; i < num; i++) {
// Read and process all INSERT/REMOVE operations in this test set
// Set isStack to false if not stack behavior detected
}
cout << (isStack ? "stack" : "not stack") << endl;
}
inFile.close();
As we read the operations from the input file we try to perform them. The INSERT operations should be performed as-is, no checks are required.
if (operation == "INSERT") {
s.push(argument);
}
The REMOVE operations require two checks to be performed: whether the stack is empty and whether the top of stack contains the same number as the argument of the REMOVE operation. If either of the checks fail then we set isStack to false.
if (operation == "REMOVE") {
if (s.empty() || s.top() != argument) {
isStack = false;
}
if (!s.empty()) {
s.pop ();
}
}
Combining this together we get:
#include <iostream>
#include <fstream>
#include <string>
#include <stack>
using namespace std;
int main () {
ifstream inFile;
inFile.open("StackTest.txt");
int num;
while (inFile >> num) {
stack<int> s;
bool isStack = true;
for (int i = 0; i < num; i++) {
string operation;
int argument;
inFile >> operation >> argument;
if (!isStack)
continue;
if (operation == "INSERT") {
s.push(argument);
}
else if (operation == "REMOVE") {
if (s.empty() || s.top() != argument) {
isStack = false;
}
if (!s.empty()) {
s.pop ();
}
}
}
cout << (isStack ? "stack" : "not stack") << endl;
}
inFile.close();
}
There is just one more thing to mention: after we read the operation name and its argument from the file we do a check
if (!isStack)
continue;
This statement is not required, it's there just for a performance improvement. If we already detected that the given test set does not correspond to a stack then we don't need to perform all the remaining operations in this test set, we just skip them. You can safely remove this statement without influencing the result.

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.

Stack (Data structure) implementation

So I'm just starting to learn about data structures through a course on Coursera and I learned that it's possible to create a stack data structure by using an array. I was just wondering if what I have written is what a stack is supposed to do.
#include <iostream>
using namespace std;
const int MAX_SIZE = 10000;
class Stack {
public:
Stack();
~Stack();
void push(int n);
void pop();
int top();
bool isEmpty() const;
void print() const;
private:
int* array [MAX_SIZE];
int curNum;
};
Stack::Stack() {
curNum = 0;
}
Stack::~Stack() {
for (int i = 0; i < curNum; ++i)
delete array[i];
}
void Stack::push(int n) {
if (curNum >= MAX_SIZE) {
cout << "reached maximum capacity...can't add an element\n";
return;
}
array[curNum] = new int(n);
curNum++;
}
void Stack::pop() {
delete array[curNum];
curNum--;
}
int Stack::top() {
return *array[curNum];
}
void Stack::print() const{
for (int i = 0; i < curNum; ++i)
cout << *array[i] << endl;
}
bool Stack::isEmpty() const{
return curNum == 0;
}
int main () {
Stack stack;
stack.push(5);
stack.print();
stack.pop();
}
Also, I see that a lot of people don't use dynamic memory allocation for this kind of task. Is there a reason why? It seems like specifying a size for the array at compile time might lead to insufficient memory or over-allocating memory to me
Yes, this is one way to implement a stack. The important thing that defines a stack is LIFO (last in, first out). So as long as you are only adding to and removing from the top, then that is a stack. Think of it as a stack of dishes; if 10 dishes are put one by one into a stack, and then one by one removed from said stack, the first dish put on will also be the last dish removed. You can't remove a dish that's not at the top, as it is covered by all the dishes above it. The same is true with a stack data structure.
So your implementation is indeed a stack.
The stack we use when we want something in reverse order and stack also takes constant time means O(1) time to push and pop means to remove or to add it will work much faster

How to implement a dynamically resizable stack in C++?

my code right now is just a simple stack that has push, pop, and display methods. How can I change my stack so that the size of the stack dynamically resizes based on the number of elements entered? So, for example, if the stack is full, I create a new stack that is twice the size of the original, and copy the data to the new stack.
Thanks.
#include <iostream>
#include <stdexcept>
using namespace std;
class Stack
{
private:
int *p;
int top,length;
public:
Stack(int = 0);
~Stack();
void push(int);
int pop();
void display();
};
Stack::Stack(int size)
{
top=-1;
length=size;
while(length <= 0) //If the stack size is zero, allow user to mention it at runtime
{
cout<<"Stack of zero size"<<endl;
cout<<"Enter a size for stack : ";
cin >> length;
}
p=new int[length];
}
Stack::~Stack()
{
delete [] p;
}
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
throw overflow_error("Can't push onto a full stack");
}
else
{
top++;
p[top]=elem;
}
}
int Stack::pop()
{
if(top==-1)
{
throw underflow_error("Can't pop from an empty stack");
}
int ret=p[top];
top--;
length--;
return ret;
}
void Stack::display()
{
for(int i = 0; i <= top; i++)
cout<<p[i]<<" ";
cout<<endl;
}
int main()
{
int len;
cout<<"Enter a size for stack : ";
cin >> len;
Stack s1(len);
try{
s1.push(1);
s1.display();
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
}
catch(overflow_error){
cerr<< "Illegal operation. Cannot push onto a full stack.";
return -1;
}
catch(underflow_error){
cerr<< "Illegal operation. Cannot pop from an empty stack.";
return -1;
}
}
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
int* newp = new int[length * 2];
std::memcpy(newp, p, sizeof(int) * length);
delete[] p;
p = newp;
top++;
p[top]=elem;
length*=2;
}
else
{
top++;
p[top]=elem;
}
}
The stack class in the standard library (std::stack) solves this by delegating to a container class such as std::vector. That's slightly cheating, though.
However, the idea behind std::vector<> is fairly straightforward and reusable. When you hit the maxiumum size, do the following things in order:
Allocate new memory. No big problem if it fails (no data lost)
Copy all existing elements over. Use std::uninitialized_copy not std::copy
Swap the new and old pointer
Delete the old objects
Free the old allocation
One simple way is to double the stack size each time pushing a new element would overflow the stack. In that instance, you detect the potential overflow and then you would use declare a new int array that is twice the size of the old one and then copy the old array into this new array and reassign the pointer to that new array and delete the old array. The are other more optimal ways, but that is a simplistic way of doing it, you can use up considerably more memory than is necessary to add the new item, but it's a lot faster than reallocating with every new item that would overflow your stack.
Instead of throwing the exception overflow_error("Can't push onto a full stack") you can allocate more memory using new and copy the contents to that memory and release the previously allocated memory(memory swapping).
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
//throw overflow_error("Can't push onto a full stack");
int *pTemp = new int[length + 10/*value u want to increment*/];
memcpy(p,pTemp,length); //for using this include stdlib
delete[] p;
p = pTemp;
}
top++;
p[top]=elem;
}