C ++ 동적 배열 액세스 위반
-
12-09-2019 - |
문제
**** 원래 게시물의 Numcars에 대한 혼란에 대해 죄송합니다. 원래 ******와 일치하도록 코드를 수정했습니다.
다음 학업 프로그램은 원래 문제의 단순화 된 버전이지만 아직 해결하지 못한 문제에 중점을 둡니다. 이 문제에는 2 개의 클래스와 주요 방법이 있으며 2 개의 클래스는 딜러 클래스와 자동차 수업으로 구성됩니다. 딜러 클래스에는 개인 자동차* 포인터가있어 딜러 생성자의 동적 배열로 초기화됩니다. 딜러의 ADDCAR 메소드가 호출되면 기본 메소드에서 오류가 발생합니다. 주요 방법에서 I의 의도적으로 딜러 변수를 ADDCAR (Dealer & D) 메소드로 전달하여 원래 응용 프로그램의 구조를 모방합니다. ADDCAR 방법은 자동차를 실행할 때 액세스 위반이 발생하는 딜러의 AddCar (Const Car & Car) 방법을 호출합니다 [NumCars ++] = CAR; 자동차 [numcars ++] = 자동차가 액세스 위반을 초래하는 이유를 설명해 주시겠습니까?
/**********************************Dealer.h**************************/
#include <cstdlib>
#include "Car.h"
using namespace std;
class Dealer
{
public:
Dealer(int maxCars = DEFAULT_MAX_CARS)
: numcars (0) {cars = 새 차 [Maxcars];}
~Dealer(){delete [] cars;}
int getTotalCars() const { return numCars;}
void addCar(const Car& car)
{
cars[numCars++] = car; // Access Violation
}
Car* begin(){return cars;};
Car* end(){ return cars + numCars;}
setnumcars (int count) {numcars = count;}
private:
static const int DEFAULT_MAX_CARS = 10;
Car* cars;
int numCars;
};
/**********************************Car.h**********************/
#include <cstdlib>
#include <string>
using namespace std;
class Car{
public:
Car()
: year(0), make(""), model("")
{}
Car(int year, string make, string model)
: year(year), make(make), model(model)
{}
string getMake() const {return make;}
void setMake(string make){this->make=make;}
string getModel() const {return model;}
void setModel(string model){this->model=model;}
int getYear() const {return year;}
void setYear(int year){this->year=year;}
private:
int year;
string make;
string model;
};
ostream& operator<< (ostream& out, const Car& car)
{
out << car.getYear() << " " << car.getMake() << " " << car.getModel();
return out;
}
/**********************************Main.cpp**********************/
#include <cstdlib>
#include <iostream>
#include "Dealer.h"
using namespace std;
void addCar(Dealer& d);
int main(int argc, char *argv[])
{
Dealer d;
addCar(d);
system("PAUSE");
return EXIT_SUCCESS;
}
void addCar(Dealer& d)
{
d = Dealer();
d.addCar(Car(2007, "Honda", "Civic"));
cout << d.getTotalCars() << " total cars" << endl;
}
해결책
void addCar(const Car& car)
{
cars[numCars++] = car; // Access Violation
}
당신은 numcars를 초기화하지 않습니다 - 그것은 거의 0이 아닌 힙의 값을 포함합니다. 이로 인해 자동차 배열 끝을 넘어 접근 할 수없는 메모리로 읽을 수 있습니다. 생성자에서 Numcars를 0으로 설정해야합니다.
또한 자동차 배열을 오버런하지 않도록 Addcar에 약간의 수표가 있어야합니다.
편집하다:
코드에는 "d = 딜러 ();"과 같은 다른 문제가 있습니다. 새로운 딜러를 만들고 당신이하고 싶은 일이 아닌 것 같습니다.
생성자/파괴자에 추가 추적을 추가하여 실제로 불리는 생성자가 실제로 생각되는지 확인하십시오. 대리점 () ()가 지정한 기본 인수로 생성자를 호출해야하지만 기본 생성자를 얻지 못하면 기본 생성자를 가져 오는 것으로 보입니다. .
다른 팁
당신은 초기화하지 않습니다 numCars
어디서나 0으로 설정해야합니다.
Dealer(int maxCars = DEFAULT_MAX_CARS) :
numCars(0)
{
cars = new Car[maxCars];
}
원시 포인터를 사용해야합니까? 그것을 마무리하고 사용하지 않는 이유는 무엇입니까? std::vector
대신에?
위 코드의 어떤 것도 딜러를 초기화합니다 :: numcars. 그러므로 그것은 임의의 쓰레기 일 수 있습니다.
어쩌면 나는 그것을 보지 못했지만 처음에는 Numcars를 어디에 설정합니까?
이것은 A처럼 보입니다 메모리 누출 그 이후로, 당신은 자동차 바늘:
setNumCars(0) {cars = new Car[maxCars];}
그리고이 코드는 실제로 오버플로 조건을 방지해야합니다.
void addCar(const Car& car)
{
cars[numCars++] = car; // Access Violation '
}
다음과 같은 일을함으로써 :
void addCar(const Car& car)
{
if (numCars < maxCars)
cars[numCars++] = car; '
else
// throw and exception .....
// or better still grow the cars buffer
}
cars[numCars++] = car; // Access Violation
게시 된 코드에서 문제가 없습니다. 다른 곳에 문제가있을 수 있습니까?
아마도 다음을 시도 할 수 있습니다.
배열을 벡터로 변경하고 at ()를 사용하여 out_of_range 예외를 포착하십시오. 같은 것 :
std::vector<int> myVec; try { int x = myVec.at(0); } catch(std::out_of_range& oor) { printf("\nout of range "); }