中断;导致段故障

break; causing segment fault

本文关键字:故障 段故障 中断      更新时间:2023-10-16

我正在使用堆栈进行括号检查。包含中断if else语句之一;语句导致段错误。

我尝试删除中断程序运行良好,但打印了错误的答案,因为需要中断才能打印正确的输出。这种段故障的原因是什么?中断不会访问任何内存单元。对吗?

问题链接

#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;
}

因此,首先提供有关std::stack的一些背景信息,这些信息将在以后变得相关:

按合约编程的风格是,拥有非空堆栈是调用 pop 的先决条件,并且在不满足其前提条件的情况下调用方法具有未定义的结果。

请注意,虽然我找不到一个来源说当堆栈中有 0 个元素时s.top()是坏的,但出于同样的原因,我会假设它也会很糟糕。

为什么这很重要?好吧,未定义的行为可以做任何事情,包括段错误。只要把它放在你的脑后。

所以,这段代码就在这里:

comp=s.top();

如果您遇到s空无一物的情况,您有其他东西从std::cin进来,会发生什么?例如,如果您在括号的末尾有一个额外的 ( 集,如下所示:

()()) // <-- extra )

()s 取消了,但那 ( 仍然存在。因此,当您尝试引用顶部时,什么都没有。这可能是导致崩溃的原因。

在尝试引用顶部之前,您需要检查此行周围s以确保它不为空:

if(!s.empty()) {
comp=s.top();
}

您可能还应该在pop()左右执行此操作:

if(c==')' && comp=='(' && !s.empty())
s.pop();

或者类似的东西。你的逻辑可能需要一些修改,但希望这能给你带来想法。

导致崩溃的原因是,在平衡输入的情况下,您的循环没有终止。所以你最终会从一个空堆栈中弹出一些东西。

您应该使用 do while 循环对此进行编码

do
{
...
if (c == ')' && comp != '(')
break;
...
}
while (!s.empty());
if (s.empty())
cout << "balancedn";
else
cout << "not balancedn";

尽管即便如此,您也需要同步输入。也许你应该阅读整个输入(也许每行一个字符串?(,然后处理输入字符串。在这种情况下,您可以将 do while 循环替换为 for 循环,例如for (char c : input)