You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++栈/链表实现RPN计算器遇EXC_BAD_ACCESS错误求助

解决你的RPN计算器崩溃问题

我仔细排查了你的代码,发现多个内存访问漏洞和逻辑错误导致了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:42:19