C++ 動的配列アクセス違反
-
12-09-2019 - |
質問
**** 元の投稿で numCars に関して混乱を招いてしまい申し訳ありません。元の ****** と一致するようにコードを修正しました。
次の学術プログラムは元の問題の簡略版ですが、私がまだ解決していない問題に焦点を当てています。この問題には 2 つのクラスと main メソッドがあり、2 つのクラスは Dealer クラスと Car クラスで構成されます。Dealer クラスには、Dealer のコンストラクターで動的配列に初期化されるプライベート Car* ポインターがあります。Dealer の addCar メソッドが呼び出されるときに、main メソッドでエラーが発生します。main メソッドでは、元のアプリケーションの構造を模倣するために、意図的に Dealer 変数を addCar(Dealer& d) メソッドに渡します。次に、addCar メソッドはディーラーの addCar(const Car& car) メソッドを呼び出します。cars[numCars++]=car; を実行するとアクセス違反が発生します。cars[numCars++]=car がアクセス違反になる理由を説明していただけますか
/**********************************Dealer.h**************************/
#include <cstdlib>
#include "Car.h"
using namespace std;
class Dealer
{
public:
Dealer(int maxCars = DEFAULT_MAX_CARS)
:numcars(0){cars = new car [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を設定する必要があります。
あなたは車の列がオーバーランしないように、この上に、あなたはaddCarでいくつかのチェックを持っている必要があります。
EDITます:
のコードといくつかの他の問題がある - 例えば、「D =ディーラー();」新しいディーラーを作成し、あなたが何をしたいかではないようですaddCarsに参照渡し1を上書きします。
ディーラーが()を使用すると、指定されたデフォルト引数でコンストラクタを呼び出すべきであることが表示されますが、それはなってきていない場合 -あなたが思うコンストラクタが実際に呼び出されていることを確認するために、コンストラクタ/デストラクタにいくつかの追加のトレースを追加してみてくださいデフォルトコンストラクタます。
他のヒント
あなたはどこにでもnumCars
を初期化していない、あなたは0に設定する必要があります:
Dealer(int maxCars = DEFAULT_MAX_CARS) :
numCars(0)
{
cars = new Car[maxCars];
}
あなたは生のポインタを使用する必要がありますか?なぜそれをラップし、代わりにstd::vector
を使わないのでしょうか?
上記のコードでは何もディーラー:: numCarsを初期化しません。したがって、任意のランダムなゴミすることができます。
たぶん私はそれを見ていないよしかし、どこで最初にnumCarsを設定するのですか?
これは、あなたがで開催された前回のメモリを解放しませんので、私には、のメモリリークのようになります。の車のポインタます:
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() を使用して範囲外例外をキャッチしてみてください。何かのようなもの:
std::vector<int> myVec; try { int x = myVec.at(0); } catch(std::out_of_range& oor) { printf("\nout of range "); }