2010-11-05 5 views
1

Je travaille sur un programme de validation d'e-mail pour ma classe cmpsci et je rencontre des problèmes avec cette partie. Ce que je fais est de lire une liste de domaines de premier niveau valides à partir d'un fichier texte dans une classe de vecteur que j'ai écrite moi-même (je dois malheureusement utiliser une classe de vecteur personnalisé). Le problème est que le programme lit et ajoute les premiers domaines au vecteur tous bien et bien, mais se bloque quand il arrive à la ligne "org". Je suis complètement perplexe pourquoi cela fonctionne pour les premiers, puis se bloque. En outre, je dois utiliser une classe de chaînes personnalisée; C'est pourquoi j'ai la fonction bizarre getline (donc j'obtiens l'entrée dans un char * pour mon constructeur String). J'ai essayé d'utiliser la classe de chaînes standard avec cette fonction et elle s'est tout de même écrasée de la même manière afin que je puisse exclure la source du problème étant ma classe de chaînes. L'ensemble du programme est assez important et je ne poste que les parties les plus pertinentes. Faites-moi savoir si plus de code est nécessaire s'il vous plaît. Toute aide serait géniale car je n'ai aucune idée d'où aller à partir d'ici. Merci!C++: Blocage du programme lors de l'ajout d'un objet à la classe de vecteurs personnalisée

La fonction ReadTlds:

void Tld::ReadTlds() { 
    // Load the TLD's into the vector 
    validTlds = Vector<String>(0); // Init vector; declaration from header file: "static Vector<String>validTlds;" 
    ifstream in(TLD_FILE); 
    while(!in.eof()) { 
     char tmpInput[MAX_TLD_LENGTH]; // MAX_TLD_LENGTH equals 30 
     in.getline(tmpInput, MAX_TLD_LENGTH); 
     validTlds.Add(String(tmpInput)); // Crashes here! 
    } 
} 

Ma classe personnalisée vecteur:

#pragma once 

#include <sstream> 

#define INIT_CAPACITY 100 
#define CAPACITY_BOOST 100 

template<typename T> class Vector { 
public: 
// Default constructor 
    Vector() { 
    Data=NULL; 
    size=0; 
    capacity=INIT_CAPACITY; 
    } 
// Init constructor 
Vector(int Capacity) : size(0), capacity(Capacity) { 
    Data = new T[capacity]; 
} 

// Destructor 
~Vector() { 
    size=0; 
    Data = NULL; 
    delete[] Data; 
} 

// Accessors 
int GetSize() const {return size;} 

T* GetData() {return Data;} 

void SetSize(const int size) {this->size = size;} 


    // Functions 
    void Add(const T& newElement) { 
    Insert(newElement, size); 
    } 

    void Insert(const T& newElement, int index) { 
    // Check if index is in bounds 
    if((index<0) || (index>capacity)) { 
    std::stringstream err; 
    err << "Vector::Insert(): Index " << index << " out of bounds (0-" << capacity-1 << ")"; 
    throw err.str(); 
    } 

    // Check capacity 
    if(size>=capacity) 
    Grow(); 

    // Move all elements right of index to the right 
    for(int i=size-1; i>=index; i--) 
    Data[i+1]=Data[i]; 

    // Put the new element at the specified index 
    Data[index] = newElement; 
    size++; 
    } 

    void Remove(int index) { 
    // Check if index is in bounds 
    if((index<0) || (index>capacity-1)) { 
    std::stringstream err; 
    err << "Vector::Remove():Index " << index << " out of bounds (0-" << capacity-1 << ")"; 
    throw err.str(); 
    } 

    // Move all elements right of index to the left 
    for(int i=index+1; i<size; i++) 
    Data[i-1]=Data[i]; 
    } 

// Index operator 
T& operator [] (int index) const { 
    // Check if index is in bounds 
    if((index<0) || (index>capacity-1)) { 
    std::stringstream err; 
    err << "Vector operator[]:Index " << index << " out of bounds (0-" << capacity-1 << ")"; 
    throw err.str(); 
    } 
return Data[index]; 
} 

// Assignment oper 
Vector<T>& operator = (const Vector<T>& right) { 
    Data = new T[right.GetSize()]; 
    for(int i=0; i<right.GetSize(); i++) 
    Data[i] = right[i]; 
    size = right.GetSize(); 
    return *this; 
} 

    private: 
T *Data; 
int size; // Current vector size 
int capacity; // Max size of vector 

void Grow() { 
    capacity+=CAPACITY_BOOST; 
    T* newData = new T[capacity]; 
    for(int i=0; i<capacity; i++) 
    newData[i] = Data[i]; 

    // Dispose old array 
    Data = NULL; 
    delete[] Data; 
    // Assign new array to the old array's variable 
    Data = newData; 
} 
    }; 

Le fichier d'entrée:

aero 
asia 
biz 
cat 
com 
coop 
edu 
gov 
info 
int 
jobs 
mil 
mobi 
museum 
name 
net 
org <-- crashes when this line is read 
pro 
tel 
travel 

L'erreur Visual Studio lancers francs est:

Unhandled exception at 0x5fb04013 (msvcp100d.dll) in Email4.exe: 0xC0000005: Access violation reading location 0xabababbb. 
+0

affichez le message d'erreur. cela va aider un peu :) – Stephano

+0

SO n'est pas sur le débogage de votre application pour vous. Prenez des mesures de débogage de base pour réduire la complexité et isoler la panne; Vous allez probablement résoudre le problème vous-même, et si vous ne le faites pas, vous aurez au moins un bloc de code plus facile à gérer. – meagar

+0

Megar, j'ai identifié la ligne exacte sur laquelle le programme se bloque. Il a un commentaire à côté de ci-dessus dans la fonction ReadTlds. J'ai seulement posté le code pertinent. Excusez-moi d'avoir posté toute la classe des vecteurs, mais j'ai l'impression que le problème se situe à l'intérieur, mais je n'ai aucune idée d'où. – Mike

Répondre

0

également dans le cteur par défaut vous

Data = NULL; 
capacity=INIT_CAPACITY; 

(EDIT: explication élargie ici) Mais jamais allouez la mémoire pour les données. Devrait-il pas:

Vector() { 
    Data= new T[INIT_CAPCITY]; 
    size=0; 
    capacity=INIT_CAPACITY; 
    } 

Et enlever est manquant

--size 

EDIT: lecteurs Compagnons me aider:

Data est de type T* mais partout ailleurs vous assignez et l'allouer comme T au lieu de T *. Mes jours C++ sont trop longtemps partis pour se rappeler si l'utilisation d'un T & résout réellement cela.

Aussi, je ne me souviens pas que si vous avez un tableau de pointeurs et que vous le détruisez, le dteur pour les instances uniques dans le tableau est détruit.

Egalement dans l'opérateur d'affectation, ne copiez-vous pas les piqueurs? Il faut donc compter sur le fait que l'instance d'où vous avez copié n'est jamais effacée (car alors vos objets seraient également morts).

hth Mario

+0

Merci pour cette capture dans la fonction de suppression; Cela a été corrigé. Que voulez-vous dire par ne pas allouer de la mémoire pour la variable de capacité? Est-ce que lui donner une valeur de INIT_CAPACITY (qui est égale à 100) ne l'alloue pas avec de la mémoire? – Mike

+0

Désolé, mauvaise formulation. J'ai élargi mon explication. Bien sûr, la mémoire de l'int elle-même est allouée mais pas pour les données. –

+0

Merci encore Mario, j'ai corrigé cela. – Mike

1

modifier c'est une nuit en retard et j'ai mal lu votre code, mais je quitte mon poste pour commenter Retour

+0

Salut biryree! Même si j'initialise le vecteur avec "Vector (100)" il se bloque toujours de la même manière. Il fonctionne comme pour les 16 premières lignes du fichier d'entrée, mais se bloque le 17. – Mike

+0

@Mike désolé, je me trompais et mal interprété votre code. Matthew Flaschen est correct et votre fonction 'Grow()' ne se comporte pas correctement. – birryree

+0

Merci birryree, j'ai réparé la fonction de croissance. – Mike

4

Le problème est dans votre fonction grow:

void Grow() { 
    capacity+=CAPACITY_BOOST; 
    T* newData = new T[capacity]; 
    for(int i=0; i<capacity; i++) 
    newData[i] = Data[i]; 

vous augmentez la capacité, mais copier des éléments qui n'existaient pas dans l'ancien tableau. Il devrait être quelque chose comme:

void Grow() { 
    int old_capacity = capacity; 
    capacity+=CAPACITY_BOOST; 
    T* newData = new T[capacity]; 
    for(int i=0; i<old_capacity; i++) 
    newData[i] = Data[i]; 

Vous NULL également des données avant supprimer à la fois pousser et destructor, ce qui provoque une fuite de mémoire. Dans les deux cas, vous n'avez pas du tout besoin de le paramétrer sur NULL, car il n'y a pas de double suppression accidentelle (dans Grow, il est immédiatement défini sur un nouveau pointeur, dans le destructeur la durée de vie de l'objet est terminée). Donc, juste

delete[] Data; 

seul est bon.

Je pense aussi

if(size>=capacity) 

peut être:

if(size == capacity) 

puisque la taille ne devrait jamais être sur la capacité. Cela signifierait que vous avez déjà débordé le tampon.

+0

Merci Matthew. J'ai corrigé la fonction de croissance ainsi que la fuite de mémoire (mes yeux ont glissé sur ces lignes des milliers de fois sans jamais attraper ça). Le programme plante maintenant dans le constructeur init de la classe de vecteurs que j'essaye actuellement de déboguer. Votre aide est très appréciée! – Mike

+0

@Mike, je ne vois pas comment il pourrait se bloquer dans un constructeur de vecteur. En passant, le problème de fuite de mémoire s'applique également au destructeur. –

+0

Mes excuses, j'ai parcouru le code un peu plus et même si le constructeur par défaut est appelé, ce qui initialise le tableau de données à "Data = new T [INIT_CAPACITY];" (Je l'ai corrigé selon les suggestions d'autres lecteurs) lorsque la fonction Insert est appelée, Data est égal à un mauvais pointeur. Cela semble être un travail pour demain. Je suis resté trop longtemps aujourd'hui. : p Et oui, j'ai corrigé le problème de fuite de mémoire dans le destructeur aussi. – Mike

1

Matthew a probablement raison. Pourtant, il y a une leçon précieuse à apprendre ici.Lorsque vous rencontrez un problème comme celui-ci, n'arrêtez pas votre code dans votre fonction ReadTlds. Continuez à marcher dans la classe Vector. Des fonctions comme Insert et Grow retiennent probablement l'erreur, mais si vous ne les parcourez pas, vous ne la trouverez jamais.

Le débogage est une compétence très spéciale. Il faut beaucoup de temps pour l'obtenir.

+0

Merci pour le conseil Stephano. Je marchais dans mes cours de cordes et de vecteurs, mais j'ai oublié de le mentionner ici. Croyez-moi, j'ai passé la majeure partie de la journée à déboguer et à essayer tout ce que je pouvais imaginer pour comprendre ce qui n'allait pas avec ce programme. Stack Overflow est toujours mon dernier recours. – Mike

+0

Génial, c'est bon à entendre. Le débogage est vraiment l'un des arts les plus subtils de la programmation, et nous avons tous des jours où nous regardons le code pendant des heures et ne pouvons tout simplement pas le comprendre. – Stephano

Questions connexes