租车程序输入结束日期后触发内存访问错误(0xC0000005)求助
我的C++租车程序分为Administration、Authentication、Client三个模块,输入租车结束日期后程序短暂冻结,随后抛出错误码-1073741819(对应0xC0000005,内存访问违规)。经调试确认问题出在rentCar和writeRentalCarsToCSV函数中,相关代码如下:
#include "Client.h" #include <fstream> #include <sstream> #include <iostream> using namespace std; struct Car { string plateNumber; string brand; int year; string model; double pricePerDay; string color; }; struct Date { string startDate; string endDate; }; struct Rental { string idNumber; string plateNumber; Date d; }; Car* readCarsFromCSV(const string& filename, int& numCars) { ifstream file(filename); if (!file.is_open()) { cout << "Error: Unable to open " << filename << " for reading." << endl; numCars = 0; return nullptr; } Car* cars = nullptr; string line; int index = 0; while (getline(file, line)) { if (line.empty()) continue; stringstream ss(line); if (index == 0) { cars = new Car[1]; } else { Car* temp = new Car[index + 1]; for (int i = 0; i < index; ++i) { temp[i] = cars[i]; } delete[] cars; cars = temp; } getline(ss, cars[index].plateNumber, ','); getline(ss, cars[index].brand, ','); string yearStr; getline(ss, yearStr, ','); bool validYear = true; for (char c : yearStr) { if (!isdigit(c)) { validYear = false; break; } } if (validYear && !yearStr.empty()) { cars[index].year = stoi(yearStr); } else { cerr << "Invalid year: '" << yearStr << "' in line: " << line << endl; cars[index].year = 0; } getline(ss, cars[index].model, ','); string priceStr; getline(ss, priceStr, ','); try { cars[index].pricePerDay = stod(priceStr); } catch (const invalid_argument& e) { if (!priceStr.empty()) { cerr << "Invalid price: " << priceStr << " in line: " << line << endl; } cars[index].pricePerDay = 0.0; } getline(ss, cars[index].color); index++; } file.close(); numCars = index; return cars; } void writeRentalCarsToCSV(const Rental* rentals, int numRentals) { ofstream file("C:\\Games\\Car Rental Program\\rentalcars.csv"); if (!file.is_open()) { cout << "Error: Unable to open rentalcars.csv for writing." << endl; return; } file << "User ID,Plate Number,Start Date,End Date" << endl; for (int i = 0; i < numRentals; ++i) { if (i < numRentals && rentals[i].idNumber != "" && rentals[i].plateNumber != "" && rentals[i].d.startDate != "" && rentals[i].d.endDate != "") { file << rentals[i].idNumber << "," << rentals[i].plateNumber << "," << rentals[i].d.startDate << "," << rentals[i].d.endDate << endl; } } file.close(); cout << "Rented cars data written to rentalcars.csv successfully." << endl; } bool checkAvailability(const Rental* rentals, int numRentals, const string& plateNumber, const string& rentedDate) { for (int i = 0; i < numRentals; ++i) { if (rentals[i].plateNumber == plateNumber && rentals[i].d.startDate <= rentedDate && rentals[i].d.endDate >= rentedDate) { return false; } } return true; } void rentCar(Rental*& rentals, int& numRentals, const string& plateNumber, const string& startDate, const string& endDate) { //this is where i believe the error is if (numRentals < 0) { cout << "Error: numRentals is not initialized properly." << endl; return; } if (numRentals % 10 == 0) { Rental* temp = new Rental[numRentals + 10]; if (!temp) { cout << "Error: Memory allocation failed." << endl; return; } for (int i = 0; i < numRentals; ++i) { temp[i] = rentals[i]; } delete[] rentals; rentals = temp; } rentals[numRentals] = { to_string(numRentals + 1), plateNumber, {startDate, endDate} }; ++numRentals; writeRentalCarsToCSV(rentals, numRentals); cout << "Car rented successfully!" << endl; }
核心问题点
未初始化的
rentals指针
若调用rentCar前,rentals未被初始化为nullptr而是野指针,numRentals %10 ==0分支中执行delete[] rentals会直接触发内存访问违规,这是导致0xC0000005错误的最可能原因。数组边界访问风险
当numRentals不是10的倍数时,直接访问rentals[numRentals]看似合法,但如果初始内存分配逻辑存在遗漏(比如第一次调用前rentals未分配且numRentals不为0),会导致越界访问。冗余代码
writeRentalCarsToCSV中的if (i < numRentals)判断完全多余,外层循环已限制i的范围,但不会导致崩溃。
修复方案
1. 强制初始化指针与计数器
调用rentCar前必须确保rentals = nullptr且numRentals = 0,同时在rentCar函数开头增加校验:
if (rentals == nullptr && numRentals != 0) { cout << "Error: rentals pointer is null but numRentals is non-zero." << endl; return; } if (rentals != nullptr && numRentals == 0) { delete[] rentals; rentals = nullptr; }
2. 优化内存分配逻辑
调整初始分配逻辑,避免空指针与计数器不匹配的问题:
if (numRentals % 10 == 0) { int newSize = (numRentals == 0) ? 10 : numRentals +10; Rental* temp = new Rental[newSize]; if (!temp) { cout << "Error: Memory allocation failed." << endl; return; } for (int i=0; i<numRentals; ++i) { temp[i] = rentals[i]; } delete[] rentals; rentals = temp; }
3. 用标准容器替代手动内存管理
手动管理动态数组极易出错,建议改用std::vector<Rental>彻底规避内存问题:
void rentCar(vector<Rental>& rentals, const string& plateNumber, const string& startDate, const string& endDate) { Rental newRental; newRental.idNumber = to_string(rentals.size() +1); newRental.plateNumber = plateNumber; newRental.d.startDate = startDate; newRental.d.endDate = endDate; rentals.push_back(newRental); writeRentalCarsToCSV(rentals.data(), rentals.size()); cout << "Car rented successfully!" << endl; }
同时修改writeRentalCarsToCSV和checkAvailability的参数为const vector<Rental>& rentals,简化代码逻辑。
内容的提问来源于stack exchange,提问作者Joseph Semaan Sfeir

