2010-09-10 6 views
0

J'ai écrit mon tout premier code de modèle C++ sur un tableau extensible et j'obtiens une erreur de segmentation! Après une heure de débogage, j'ai réalisé que j'avais besoin d'aide. Quelque chose ne va pas avec le constructeur ou le destructeur, mais je ne suis pas sûr.Segmentation fault C++ templates

Le code est sur le pas prêt à être compilé. http://pastie.org/1150617

/* Expandable array in C++ */ 

#include <iostream> 
using namespace std; 

template <class T> 
class EArray{ 
private: 
    T* arr; 
    int size; 
public: 
    EArray(int l); 
    ~EArray(); 

    void setElement(int i, const T& newval); 
    void eraseElement(int i); 
    void addElement(int i, const T& newval); 
    void push(const T& newval); 
    void display(); 
}; 

template <class T> 
EArray<T>::EArray(int l){ 
    size = l; 
} 

template <class T> 
EArray<T>::~EArray(){ 
    delete [] arr; 
    arr = NULL; 
} 

template <class T> 
void EArray<T>::setElement(int i, const T& newval){ 
    if(i < size && i >= 0){ 
     arr[i] = newval; 
    } 
} 

template <class T> 
void EArray<T>::eraseElement(int index){ 
    size -= 1; 
    T* newarr = new T[size]; 
    for (int i = 0; i < size+1; i++){ 
     if (i < index){ 
      newarr[i] = arr[i]; 
     } 
     else if(i > index){ 
      newarr[i-1] = arr[i]; 
     } 
    } 
    delete [] arr; 
    arr = newarr; 
} 

template <class T> 
void EArray<T>::addElement(int index, const T& newval){ 
    size += 1; 
    T* newarr = new T[size]; 
    for(int i = 0; i < size; i++){ 
     if(i<index){ 
      newarr[i] = arr[i]; 
     } 
     else if (i == index){ 
      newarr[i] = newval; 
     } 
     else{ 
      newarr[i] = arr[i-1]; 
     } 
    } 
    delete [] arr; 
    arr = newarr; 
} 

template <class T> 

void EArray<T>::push(const T& newval){ 
    size += 1; 
    T * newarr = new T[size]; 
    for (int i = 0; i < size-1; i++){ 
     newarr[i] = arr[i]; 
    } 
    newarr[size-1]=newval; 
    delete [] arr; 
    arr = newarr; 
} 

template <class T> 
void EArray<T>::display(){ 
    for(int i = 0; i < size; i++){ 
     cout << arr[i] << endl; 
    } 
} 

int main(){ 
    EArray<int> A(6); 
    A.setElement(0,34); 
    A.setElement(1,544); 
    A.setElement(2,32); 
    A.setElement(3,324); 
    A.setElement(4,24); 
    A.display(); 
    A.addElement(3,12); 
    A.display(); 
    A.eraseElement(4); 
    A.display(); 
    A.push(32456); 
    A.display(); 
} 
+6

Où est-ce que vous obtenez une erreur de segmentation? Avez-vous attaché un débogueur à votre programme pour voir ce qui ne va pas quand il se bloque? Avez-vous réduit le code au minimum requis pour reproduire le problème? –

+0

Les questions de James sont celles auxquelles il faut toujours répondre à chaque fois que vous essayez d'analyser une erreur de segmentation. +1 – CanSpice

+0

Je pense que je dois apprendre à utiliser un débogueur. – zubinmehta

Répondre

12

Il n'a rien à voir avec les modèles. C'est juste un problème de gestion de la mémoire. Dans le constructeur de EArray, vous n'avez jamais initialisé arr. Par défaut, il contient un pointeur non valide.

Mais alors dans setElement, vous avez utilisé ce pointeur non valide arr[i] = newval;, ce qui devrait provoquer un SegFault.

Il devrait être fixable en ajoutant

arr = new T[size]; 

dans le constructeur (résultat: before, with segfault-after, running fine).

(BTW, dans la pratique, s'il vous plaît utiliser un std::vector.)

+0

oui, j'ai écrit ceci juste pour comprendre la mécanique. J'utiliserais st :: vector pour l'utiliser. Merci d'avoir répondu. – zubinmehta

0

Votre cteur n'alloue pas de mémoire pour les éléments. Et vous utilisez setElement avant de pousser des éléments dans l'objet. Donc, arr [i] dans setElement accédera à la mémoire non allouée, et AV.

1

Votre constructeur EArray n'initialise pas arr

ajouter arr = new T[size]; après la ligne 24

Ou changer pour:

template <class T> 
EArray<T>::EArray(int l) : size(l), arr(new T[size]){ 
    size = l; 
} 

Vous devez fournir une copie correcte construtor et d'affectation ainsi - ou faites-les privés pour ne pas permettre à votre Eraray d'être copié.

0

Eh bien, une chose à retenir est que vous spécifiez qu'il y a un retour d'un int dans votre fonction principale alors ne rien retourner. C'est faux. Votre erreur, cependant, provient du fait que vous définissez la taille du tableau dans le constructeur, mais ne lui allouez pas l'espace. Ainsi, lorsque vous essayez de définir le premier élément, il essaie de le définir sur la mémoire non allouée et vous vous retrouvez avec un segfault.

+2

Votre premier point est incorrect. 'main' est autorisé à avoir un' return 0 'implicite à la fin si vous ne renvoyez rien. –

1

Je suis toujours là. Mais une première erreur est:

  • le constructeur n'attribue pas, mais ne définit que la taille
  • setElement n'accéder au champ alors qu'il n'est pas affecté.

(qui semble l'être)

Questions connexes