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
相关产品推荐
相关产品推荐

