Mac HighSierra下C++队列程序入队时触发Segmentation fault 11
Segmentation Fault 11 原因分析与代码修复(队列实现)
嘿,我看到你在Atom里用GCC写队列程序时,执行入队操作触发了Segmentation fault 11——这是典型的内存访问越界问题,咱们一步步拆解问题并修复:
核心错误:入队操作访问非法内存
你的inqueue()函数里,当队列为空时(此时antrean.akhir = -1),直接执行了antrean.data[antrean.akhir] = elemen;——这意味着你在访问数组的**-1索引**,完全超出了data[MAX]的合法范围(数组合法索引是0到MAX-1),直接触发段错误。
正确的逻辑应该是:队列为空时,先把awal和akhir都重置为0,再给data[akhir]赋值,之后再自增akhir。
其他需要修正的逻辑问题
除了核心的段错误,代码里还有几个小问题也会导致异常或逻辑错误:
isfull()判断逻辑偏差:当前只检查akhir == MAX-1,但结合你的入队逻辑,akhir最终会指向队列的下一个空位置,所以应该判断akhir == MAX才是真正的满队状态。totalarray()非法内存访问:循环从i=-1开始,同样会访问data[-1]触发错误,应该从队列的起始索引awal开始遍历。cari()输出错误:你把找到的元素值加1输出了(antrean.data[i]+1),这不是索引位置,应该改为i - antrean.awal + 1(显示为队列中1开头的位置)。- 主菜单逻辑混乱:菜单里选项7是“Rata-rata Array”(计算平均值),但代码里
case 7直接exit(0),会导致用户选平均值时直接退出程序,需要调整。 cari()的状态判断遗漏:原代码没有处理“元素未找到”的提示,会导致空输出。
修正后的完整代码
#include<iostream> #include<stdlib.h> #define MAX 5 using namespace std; struct queue{ int data[MAX]; int awal, akhir; }antrean; void first(){ antrean.awal = -1; antrean.akhir = -1; } bool isfull(){ // 修正:akhir指向空位置,等于MAX时队列已满 if(antrean.akhir == MAX){ return true; }else{ return false; } } bool isempty(){ if(antrean.akhir == -1){ return true; }else{ return false; } } void tampildata(){ if(!isempty()){ // 遍历到akhir-1,因为akhir是下一个空位置 for(int i=antrean.awal; i < antrean.akhir; i++){ cout<<antrean.data[i]<<" | "; } } cout<<endl; } void inqueue(){ int elemen; if(!isfull()){ // 修正:入队前先检查队列是否已满,而非是否为空 cout<<"input data : "; cin>>elemen; if(isempty()){ // 队列为空时,初始化起始索引为0 antrean.awal = 0; } // 给当前akhir位置赋值,再自增 antrean.data[antrean.akhir] = elemen; antrean.akhir++; cout<<"data berhasil ditambah"<<endl; tampildata(); }else{ cout<<"Queue penuh"<<endl; } } void dequeue(){ tampildata(); if(!isempty()){ cout<<"mengambil data "<<antrean.data[antrean.awal]<<endl; for(int i=antrean.awal; i < antrean.akhir-1; i++){ antrean.data[i] = antrean.data[i+1]; } antrean.akhir--; // 如果队列空了,重置awal和akhir if(antrean.akhir == 0){ antrean.awal = -1; antrean.akhir = -1; } }else{ cout<<"antrean empty"<<endl; } } void cari(){ if(!isempty()){ int cari; bool state = false; cout << "Data yang dicari :"; cin >> cari; for(int i = antrean.awal; i < antrean.akhir; i++){ if (antrean.data[i] == cari) { // 修正:输出队列中的位置(从1开始计数) cout << "Data ditemukan pada posisi ke-:" << i - antrean.awal + 1 << endl; state = true; break; } } if(!state){ cout << "Data tidak ditemukan" << endl; } } else{ cout << "Antrean kosong" << endl; } } void totalarray(){ if(isempty()){ cout << "Antrean kosong, tidak bisa menghitung total" << endl; return; } int temp = 0; // 修正:从awal开始遍历到akhir-1 for(int i=antrean.awal; i < antrean.akhir; i++){ temp += antrean.data[i]; } cout << "Total nilainya :" << temp << endl; } // 新增计算平均值的函数 void ratarata(){ if(isempty()){ cout << "Antrean kosong, tidak bisa menghitung rata-rata" << endl; return; } int total = 0; int count = antrean.akhir - antrean.awal; for(int i=antrean.awal; i < antrean.akhir; i++){ total += antrean.data[i]; } cout << "Rata-rata nilainya :" << (double)total / count << endl; } int main(){ int pilihan, elemen; first(); do{ tampildata(); cout<<"1. Init"<<endl <<"2. inQueue"<<endl <<"3. deQueue"<<endl <<"4. tampil data"<<endl <<"5. Cari data"<<endl <<"6. Total nilai"<<endl <<"7. Rata-rata Array"<<endl <<"8. Nilai terbesar"<<endl <<"9. Nilai terkecil"<<endl <<"10. Clear"<<endl <<"11. Keluar"<<endl; cout<<"input pilihan :"; cin>>pilihan; switch(pilihan){ case 1: first(); break; case 2: inqueue(); break; case 3: dequeue(); break; case 4: tampildata(); break; case 5: cari(); break; case 6: totalarray(); break; case 7: ratarata(); break; case 11: exit(0); default: cout<<"Pilihan tidak valid"<<endl; } } while(pilihan != 11); return 0; }
关键修改说明
- 入队函数修正:入队前先检查队列是否已满,队列为空时初始化
awal为0,彻底避免访问负索引。 - 出队函数修正:队列清空后重置
awal和akhir为-1,保持空队状态的一致性。 - 遍历逻辑统一:所有涉及队列元素遍历的函数,都从
awal开始到akhir-1结束,杜绝越界风险。 - 菜单逻辑修正:把退出程序的逻辑移到选项11,选项7改为调用新增的平均值计算函数,匹配菜单描述。
现在你编译运行这个修正后的代码,入队操作就不会触发Segmentation fault了,其他功能也能正常工作。
内容的提问来源于stack exchange,提问作者Fikar Ali
相关产品推荐
相关产品推荐

