C++栈/链表实现RPN计算器遇EXC_BAD_ACCESS错误求助
我仔细排查了你的代码,发现多个内存访问漏洞和逻辑错误导致了EXC_BAD_ACCESS(退出码11)崩溃,下面是具体问题和修复方案:
1. 最致命的问题:非法的类成员数组
你的RPN类里声明了char calculation[];——这在C++里是不允许的,类成员不能是未指定大小的变长数组。当你用cin >> calculation输入内容时,会直接写入未分配的内存区域,造成内存 corruption,这大概率是触发崩溃的直接原因。
修复:
把它换成std::string calculation;(推荐,更安全且无需手动管理内存),或者指定固定大小的数组(比如char calculation[256];)。如果用string,putOnStack里的strlen(calculation)要改成calculation.size():
class RPN { Stack *stack; public: RPN(); int type; int result; std::string calculation; // 替换原有的char calculation[] // ... 其他成员不变 }; // 对应的putOnStack修改 void RPN::putOnStack() { for(int i = 0; i < calculation.size(); i++) if(isNum(calculation[i])) stack->push(calculation[i] - '0'); // 这里还要修复数字转换问题 }
2. 数字字符转整数的错误
你直接把char类型的数字push到栈里,比如输入'3',实际存入的是它的ASCII码值51,而不是整数3。这不仅会导致计算错误,还可能间接引发内存问题。
修复:
将字符转成对应整数,减去'0'即可:
stack->push(calculation[i] - '0');
3. List类Previous方法的逻辑漏洞
当栈里只有一个元素时(链表仅一个节点,Last()返回header),调用Previous(header)会进入无限循环,直到访问空指针的next成员,直接触发崩溃。
修复:
给Previous方法增加边界检查,处理第一个节点没有前驱的情况:
cell* List::Previous(cell *p) { if (p == header || header == nullptr) { return nullptr; // 第一个节点无前置,或链表为空 } cell* tmp = header; while(tmp != nullptr && tmp->next != p) { tmp = tmp->next; } return tmp; }
4. Stack类pop方法的逻辑错误
当链表只有一个节点时,Previous(list->Last())返回nullptr,此时调用list->Delete(c)会访问nullptr->next,直接崩溃。另外,pop方法没有检查栈是否为空,空栈调用也会出错。
修复:
修改pop方法,增加空栈检查,并处理单节点链表的情况:
element Stack::pop() { if (empty()) { cerr << "错误:栈下溢!" << endl; exit(1); // 也可以抛出异常,根据需求调整 } cell* last = list->Last(); element tmp = list->Retrieve(last); cell* prev = list->Previous(last); if (prev == nullptr) { // 这是第一个节点,直接删除header delete last; list->header = nullptr; } else { list->Delete(prev); } return tmp; }
5. List类Delete方法的边界问题
当前Delete方法假设p->next不为nullptr,如果p是最后一个节点,调用Delete(p)会访问nullptr->next,触发崩溃。
修复:
给Delete方法增加边界检查:
void List::Delete(cell *p) { if (p == nullptr || p->next == nullptr) { return; // 无可删除节点,或p是最后一个节点 } cell* tmp = p->next; p->next = p->next->next; delete tmp; }
6. List类Locate方法的空指针问题
当链表为空时,tmp = header是nullptr,访问tmp->next会直接崩溃。
修复:
先检查链表是否为空:
cell* List::Locate(element x) { if (header == nullptr) { return nullptr; } cell* tmp = header; while(tmp->next != nullptr) { if(tmp->next->element == x) return tmp; tmp = tmp->next; } return tmp; }
测试验证
做完这些修改后,输入3或3+3时程序就不会再崩溃了。后续你可以继续完善calculate、convertToRPN等方法的逻辑,完成RPN计算器的功能。
内容的提问来源于stack exchange,提问作者nuxie

