问题
I was doing parenthesis checker using the stack. One of the if else statement containing a break; statement is causing segment fault.
I tried removing the break program runs fine but prints the wrong answer as that break is needed to print correct output. What is the cause of such a segment fault? the break doesn't access any memory unit.right?
Questions link
#include <iostream>
#include<stack>
using namespace std;
int main() {
//code
int n;
char c,comp;
cin>>n;
while(n--)
{
stack<char>s;
while(cin>>c)
{
if(c=='(' || c=='{'|| c=='[')
s.push(c);
else
{
comp=s.top();
if(c==')' && comp=='(')
s.pop();
else if(c==')' && comp!='(')
{
cout<<"not balanced"<<endl;
break; //this one, if i remove this no SIGSEGV
}
if(c=='}' && comp=='{')
s.pop();
else if(c=='}' && comp!='{')
{
cout<<"not balanced"<<endl;
break;
}
if(c==']' && comp=='[')
s.pop();
else if(c==']' && comp!='[')
{
cout<<"not balanced"<<endl;
break;
}
}
}
if(s.empty())
cout<<"balanced"<<endl;
}
return 0;
}
回答1:
So, first some background information on std::stack that will become relevant later:
The programming-by-contract style would be that having a non-empty stack is a precondition of calling pop, and that calling a method without meeting its preconditions has an undefined outcome.
Please note that while I couldn't find a source that said s.top()
is bad when there are 0 elements in a stack, I'm going to assume it would also be bad for the same reason.
Why is that important? Well, undefined behavior can do anything, including segfault. Just keep that in the back of your head.
So, this code right here:
comp=s.top();
What happens if you ever run into a situation where s
is empty, you have something else coming in from std::cin
? For instance, what if you had an extra ) at the end of a parenthesis set like this:
()()) // <-- extra )
The ()
s cancel out, but that ) is still there. So, when you try to reference the top, nothing is there. This is probably what is causing the crash.
You need a check around this line to make sure s
isn't empty before you try to reference the top:
if(!s.empty()) {
comp=s.top();
}
You should also probably do this around pop()
as well:
if(c==')' && comp=='(' && !s.empty())
s.pop();
Or something to that effect. Your logic may need some reworking, but hopefully that gives you the idea.
回答2:
The crash is caused because you have no termination to your loop in the case of a balanced input. So you are going to end up popping something from an empty stack.
You should code this with a do while loop
do
{
...
if (c == ')' && comp != '(')
break;
...
}
while (!s.empty());
if (s.empty())
cout << "balanced\n";
else
cout << "not balanced\n";
Although even then you need to synchonise your input. Probably you should read the whole input (one string per line maybe?) and then work on the input string. In that case you could replace the do while loop with a for loop, e.g. for (char c : input)
来源:https://stackoverflow.com/questions/57387399/break-causing-segment-fault