2016-10-05 1 views
1

J'implémente une structure de données trie simple en C++ en utilisant struct et pointters. Quand je passe une chaîne à ajouter à trie, cela donne une erreur de segmentation dans la fonction addString().Erreur de segmentation de l'implémentation Trie C++

struct node { 
    char ch; 
    node *link[26]; 

    node() : link(){} 
}; 

node head; 


void addString(node *n, string s) { 
    if (!s.length()) return; 

    if (!n -> link[(int)s[0] - 97]) { 
     node m; 
     m.ch = s[0]; 
     n -> link[(int)s[0] - 97] = &m; 
    } 
    addString(n -> link[(int)s[0] - 97], s.substr(1)); 
} 

int main(){ 
    addString(&head, "red"); 
    return 0; 
} 

J'ai essayé les instructions de débogage et même imprimé et mis en correspondance les valeurs d'adresse du noeud nouvellement créé et celui passé récursivement, ils étaient identiques. PS J'utilise un nœud de tête comme état epsilon.

+4

S'il vous plaît ne pas utiliser le [tag: c] dans une balise: question [tag C++]. Ils sont deux tags différents pour une raison. –

+4

Le bon outil pour résoudre ces problèmes est votre débogueur. Vous devez parcourir votre code ligne par ligne * avant * de demander Stack Overflow. Pour plus d'aide, veuillez lire [Comment déboguer de petits programmes (par Eric Lippert)] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). Au minimum, vous devriez [modifier] votre question pour inclure un exemple [Minimal, Complet et Vérifiable] (http://stackoverflow.com/help/mcve) reproduisant votre problème, ainsi que les observations que vous avez faites dans le débogueur. –

+2

Recommander contre le 97. «a» est presque infiniment plus facile à interpréter. – user4581301

Répondre

2

Vous utilisez des adresses d'objets alloués sur la pile. node m; est sur la pile. Il sera supprimé dès que vous quittez un bloc if dans lequel il est déclaré. Et vous affectez son adresse à un nœud n -> link[(int)s[0] - 97] = &m; qui vit plus longtemps que cela.

1
n -> link[(int)s[0] - 97] = &m; 

vous stockez l'adresse de m alors qu'il est détruit à la fin de son champ d'application.

Vous devez repenser votre projet en gérant correctement la mémoire.

1

Il y a deux problèmes qui pourraient expliquer une erreur de segmentation:

  • le premier est que vous ajoutez un pointeur vers un objet local m dans votre tableau de liens. Dès que vous revenez de la fonction, le pointeur se balancera et vous aurez UB. Allouer correctement m: node *m = new node; Mieux: utiliser unique_ptr au lieu de pointeurs bruts.

  • Vous supposez que la chaîne ne contient que des lettres minuscules entre 'a' et 'z'. Si la chaîne contient autre chose, vous allez sortir des limites et peut provoquer une corruption de la mémoire et UB. Vous devez avoir au moins un assert()

Voici un petit correctif pour résoudre les problèmes, en fonction de votre structure actuelle et de l'approche:

struct node { 
    ... 
    node(char c=0) : link(), ch(c) {} 
    ~node() { for (int i=0;i<26; i++) delete link[i]; } 
}; 
... 
void addString(node *n, string s) { 
    if (!s.length()) return; 
    size_t c = tolower(s[0]); 
    if (c<'a' || c>'z') return; // char not ok-> do like end of string 
    if (!n -> link[c-'a']) { 
     n -> link[c-'a'] = new node(c); 
    } 
    addString(n -> link[c-'a'], s.substr(1)); 
}  

Notez que lorsque vous utilisez des pointeurs dans un struct, vous avez être très prudent sur le rule of 3. Cependant, cela ne vous fera pas de mal, car vous ne copiez pas encore de nœuds.

Online demo