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

C++类中向数组/vector添加值时程序崩溃问题求助

程序运行到Check 1后崩溃的原因分析与修复方案

我帮你排查下问题,你的程序执行到bk_borrow函数里的Check 1后崩溃,核心原因是内存越界访问,再加上一些不安全的函数使用和逻辑疏漏,具体分析和修复方法如下:

1. 直接崩溃原因:student类成员i的未初始化/非法值问题

你在issue_book函数中从Students.dat读取学生数据到全局s对象时:

if2.read((char*)&s, sizeof(s));

这里直接用二进制读取覆盖了s的所有成员,包括i变量。但student的构造函数只在对象创建时执行一次(初始化i=0),从文件读出来的i可能是之前写入的旧值,甚至是无意义的垃圾值。

当调用s.bk_borrow(no)时,如果i的值已经大于等于6(vs数组只有6个元素,索引范围是0~5),执行vs[i] = n就会触发数组越界访问,直接导致程序崩溃——这正好对应你看到的Check 1输出后崩溃的现象。

修复方法:

  • 方案一:在读取学生对象后,手动同步i和bkcount的值(因为每借一本书i和bkcount应该同步增长):
    if2.read((char*)&s, sizeof(s));
    s.i = s.bkcount; // 让i等于当前已借书籍的数量,避免越界
    
  • 方案二:在bk_borrow中增加越界检查,同时补上bkcount的更新(你之前的代码里借了书但没更新已借数量,逻辑有问题):
    void bk_borrow(int n) { 
        if(i >= 6) {
            cout<<"\n 无法借阅更多书籍,已达上限!";
            return;
        }
        cout<<"\n Check 1."; 
        vs[i] = n; 
        cout<<"\n Check 2."; 
        i++;
        bkcount++; // 同步更新已借书籍数量
    }
    
  • 方案三:彻底替换数组为std::vector<int>,从根源避免数组越界:
    class student {
        // ... 其他成员不变
        vector<int> vs; // 替换原有的int vs[6];
        // 去掉成员变量i,用vs.size()代替
    public:
        student() { bkcount = 0; }
        // ... 其他成员函数不变
        void bk_borrow(int n) { 
            if(vs.size() >=6){
                cout<<"\n 无法借阅更多书籍,已达上限!";
                return;
            }
            cout<<"\n Check 1."; 
            vs.push_back(n); 
            cout<<"\n Check 2."; 
            bkcount++;
        }
        vector<int> ret_borrowed() { return vs; }
        void bk_return(int n) { 
            for(auto it = vs.begin(); it != vs.end(); ) {
                if(*it == n) {
                    it = vs.erase(it);
                    bkcount--;
                } else {
                    it++;
                }
            }
        }
    };
    

2. 潜在隐患:不安全的gets函数导致缓冲区溢出

你的代码里大量使用gets函数(比如modify_stname()、modify_class()),这个函数不会检查输入长度,一旦用户输入的字符超过数组容量(比如stname[15]最多只能存14个有效字符加结束符\0),就会触发缓冲区溢出,破坏内存,可能引发崩溃或奇怪的逻辑错误。

修复方法:

用fgets替代gets,并手动去除换行符:

void modify_stname() { 
    fgets(stname, sizeof(stname), stdin);
    // 去掉fgets读取的换行符,避免影响后续操作
    stname[strcspn(stname, "\n")] = '\0';
}
void modify_class() { 
    fgets(Class, sizeof(Class), stdin);
    Class[strcspn(Class, "\n")] = '\0';
}

3. 其他需要补全的逻辑

  • 你当前的代码只修改了内存中的s和b对象,但没有把修改后的内容写回文件,导致借阅记录无法持久化,下次运行程序时之前的操作都会丢失。需要在修改完成后添加写回逻辑:
    // 修改完学生和书籍对象后,写回文件
    // 写回学生文件
    if2.seekp(vs.back(), ios::beg);
    if2.write((char*)&s, sizeof(s));
    // 写回书籍文件
    if1.seekp(vb[op-1], ios::beg);
    if1.write((char*)&b, sizeof(b));
    
  • bk_return函数中,用sizeof(vs)/sizeof(int)获取数组长度的写法在数组是成员变量时没问题,但如果换成vector需要改成vs.size();另外当前逻辑只是把归还的书籍号设为0,会留下无效数据,建议直接删除对应元素(用vector的话可以直接erase)。

内容的提问来源于stack exchange,提问作者XPekez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:34:35