2009-09-22 14 views
0

**** Désolé pour la confusion concernant numCars dans la publication d'origine. J'ai modifié le code pour être cohérent avec l'original ******Violation d'accès au tableau dynamique C++

Le programme académique suivant est une version simplifiée du problème original mais il se concentre sur le problème que je n'ai pas encore résolu. Il y a 2 classes et une méthode principale à ce problème et les 2 classes se composent d'une classe de revendeur et d'une classe de voiture. La classe Dealer a un pointeur Car * privé initialisé sur un tableau dynamique dans le constructeur du Dealer. L'erreur se produit dans la méthode principale lorsque la méthode addCar du revendeur est appelée. Dans la méthode principale, je passe intentionnellement la variable Dealer à la méthode addCar (Dealer & d) pour imiter la structure de l'application d'origine. La méthode addCar appelle ensuite la méthode addCar du concessionnaire (const Car & car) où la violation d'accès se produit lorsque j'exécute des voitures [numCars ++] = car; Pouvez-vous expliquer pourquoi les voitures [numCars ++] = résultats de voiture dans une violation d'accès

/**********************************Dealer.h**************************/ 
#include <cstdlib> 
#include "Car.h" 

using namespace std; 

class Dealer 
{ 
    public: 
     Dealer(int maxCars = DEFAULT_MAX_CARS) 

: numCars (0) {voitures = new voiture [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 &lt;cstdlib&gt; 
#include &lt;iostream&gt; 
#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; 
} 

Répondre

4
void addCar(const Car& car) 
{ 
    cars[numCars++] = car; // Access Violation 
} 

Vous n'initialisez numCars - il contient une valeur du tas qui est presque définitivement non nul. Cela vous amène à lire au-delà de la fin du tableau des voitures et dans la mémoire inaccessible. Vous devriez mettre numCars à 0 dans votre constructeur. En plus de cela, vous devriez avoir des vérifications dans addCar afin de ne pas dépasser le tableau des voitures.

EDIT:

Il y a quelques autres problèmes avec le code - par exemple, "d = Dealer();" crée un nouveau revendeur et écrase celui que vous passez en référence à addCars, ce qui ne semble pas être ce que vous voulez faire. Essayez d'ajouter un traçage supplémentaire au constructeur/destructors pour vérifier que les constructeurs que vous pensez être appelés sont effectivement - il semble que Dealer() devrait invoquer le constructeur avec un argument par défaut que vous avez spécifié, mais sinon il est obtenir le constructeur par défaut.

+0

Vous me battre de 10 secondes :( – GManNickG

+0

vous avez raison de ne pas l'initialisation numCars mais il a été initialisé dans le code original et je reçois toujours l'erreur de violation d'accès si je change les voitures. [numCars ++] = voiture aux voitures [0 | 1 | 2 | 3 | ...] = voiture; –

+0

J'ai modifié la signature d'addCars pour m'attendre à ce qu'un revendeur * évite de créer une nouvelle instance d'un concessionnaire mais n'a pas résolu l'accès Erreur de violation La réinitialisation de d dans la méthode addCar m'a paru suspicieuse aussi mais la changer n'a eu aucun effet –

1

Vous n'êtes pas initialiser numCars partout, vous devez le mettre à 0:

Dealer(int maxCars = DEFAULT_MAX_CARS) : 
numCars(0) 
{ 
    cars = new Car[maxCars]; 
} 

Avez-vous d'utiliser des pointeurs premières? Pourquoi ne pas envelopper et utiliser std::vector à la place?

+0

basé sur les exigences, je dois utiliser le tableau dynamique –

+0

C'est malheureux. faites le devoir avec un vecteur, donc tout le reste fonctionne, puis dépouillez le vecteur. – GManNickG

1

Rien dans le code ci-dessus n'initialise Dealer :: numCars. Il peut donc s'agir de n'importe quelle poubelle aléatoire.

1

Peut-être que je ne le vois pas mais où définissez-vous initialement numCars?

0

Cela ressemble à une me fuite de mémoire depuis, vous ne relâchez pas la mémoire précédente détenue par les voitures pointeur:

setNumCars(0) {cars = new Car[maxCars];} 

et ce code doit devriez vraiment se prémunir contre la condition de trop-plein :

void addCar(const Car& car)   
{         
    cars[numCars++] = car; // Access Violation  ' 
} 

en faisant quelque chose comme ceci:

void addCar(const Car& car)   
{         
    if (numCars < maxCars) 
     cars[numCars++] = car;  ' 
    else 
     // throw and exception ..... 
     // or better still grow the cars buffer 
} 
0
cars[numCars++] = car; // Access Violation 

Je ne vois aucun problème avec le code affiché. Peut-être un problème est ailleurs?

Probablement vous pouvez essayer ce qui suit:

  • tableaux de changement de vecteur et essayer d'utiliser au() pour attraper out_of_range exception. quelque chose comme:

    std::vector<int> myVec; 
        try 
        { 
        int x = myVec.at(0); 
    
        } 
        catch(std::out_of_range& oor) 
        { 
         printf("\nout of range "); 
        } 
    
+0

Je dois utiliser le tableau et je suis d'accord qu'il semble que cela devrait fonctionner. J'ai comparé le code à d'autres exemples de tableaux dynamiques et je n'ai encore trouvé aucune anomalie. –