IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

débutant avec unique_ptr (segmentation_fault)


Sujet :

C++

  1. #1
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut débutant avec unique_ptr (segmentation_fault)
    Bonjour,

    voici du code pour montrer mon problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    // la méthode ou ça plante
    template<typename Type, typename Label>
    void Automaton<Type,Label>::NewTransitionForState(const Label& name, Transition<Type,Label>* transition, State<Type,Label>* stateReached)
    {
        for( auto s : statesVector )
            if ( s->GetName() == name )//<- ici la segmentation fault
                s->NewTransition(transition, stateReached);
     
        //s est normalement du type std::unique_ptr<Automaton<Type, Label>>
     
    }
     
    //le constructeur
    template<typename Type, typename Label>
    Automaton<Type,Label>::Automaton(const Label& name, const T_statesVector& statesVector) :
        statesVector(statesVector),
        name(name),
        up_currentState(nullptr)//<- si j'essayais d'y accéder tel quel je comprendrais
    {
    }
     
    //création d'un nouvel état
    template<typename Type, typename Label>
    void Automaton<Type,Label>::NewState(State<Type,Label>* state)
    {
        statesVector.push_back(state);
        if (up_currentState == nullptr)
            up_currentState = std::unique_ptr<State<Type, Label>>(state);//passera forcément par là, dailleurs j'avais aucun problème avec un pointeur classique
    }
     
    //la méthode qui appelle la méthode qui plante
    using namespace std;
    int compteur = 0;
    cout << "->";
    while(up_automaton->up_currentState->GetType() != StateType::finalState)
    {
        cout << up_automaton->up_currentState->GetName() <<"(";
        const std::string& currentStateName = std::string(up_automaton->up_currentState->GetName());
        if (currentStateName == "Etat Initial")
        {
            cout << "test";
            compteur++;
            if (compteur==1000)
            {
                cout << up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 3")->GetValue();
                up_automaton->UpdateState(up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 3"));
            }
            else
            {
                cout << up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 2")->GetValue();
                up_automaton->UpdateState(up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 2"));
            }
        }
        else if (currentStateName == "Etat 2")
        {
            cout << up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 4")->GetValue();
            up_automaton->UpdateState(up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 4"));
        }
        else if (currentStateName == "Etat 3")
        {
            cout << up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 5")->GetValue();
            up_automaton->UpdateState(up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 5"));
        }
        else if (currentStateName == "Etat 4")
        {
            cout << up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 1")->GetValue();
            up_automaton->UpdateState(up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 1"));
        }
        else
            cout << L"nom de la transition : " << up_automaton->up_currentState->GetTransitionByName("transition vers l'etat numero 1")->GetName();
     
        cout << ") ->" << endl;
    }
    cout << up_automaton->up_currentState->GetName() << endl;
    }
    En l'état, il semblerait que je tape dans un objet non initialisé ou vide...

    vous avez une explication ?

    Merci d'avance pour votre aide.
    Nullius in verba

  2. #2
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for( auto s : statesVector )
    Si il y a bien une chose que j’exècre, c'est cette manie d'écrire des auto dans un range for loop (for (auto a : b)...). Quand je vois que même Herb Sutter ou Scott Meyer le recommande ça me désespère.

    Je trouve le range for loop d'une élégance et concision extraordinaire car il suffit d'un coup d’œil pour avoir sous les yeux toutes les info pertinentes (type de l’élément en cours, nom de l’élément en cours, nom du conteneur sur lequel on boucle). En revanche si on s'amuse à mettre du auto là-dedans alors on ne peut plus comprendre la boucle juste en la regardant, il faut chercher parfois complètement ailleurs dans le code quel est le type du conteneur pour trouver le type de l’élément. Et donc par exemple, impossible pour nous de savoir quel est le type réel de s vu qu'on ne sait pas quel est le type réel de T_statesVector

    D'après ce que tu dis le vrai type serait :

    for(std::unique_ptr<Automaton<Type, Label>> s : statesVector)

    Je ne comprends pas comme ça peut compiler. On ne peut pas prendre un unique_ptr par valeur vu qu'il n'est pas copiable. Du coup je doute fortement que stateVector soit vraiment du type std::vector<std::unique_ptr<...>>

    D'ailleurs si c'était le cas, le code suivant ne compilerais pas non plus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    //le constructeur
     template<typename Type, typename Label>
        Automaton<Type,Label>::Automaton(const Label& name, const T_statesVector& statesVector) :
        statesVector(statesVector), // pas possible ici
    Si statesVector contenait vraiment des unique_ptr, on ne pourrait pas le copier comme ça...

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur .NET/C/C++
    Inscrit en
    Septembre 2007
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET/C/C++
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2007
    Messages : 71
    Points : 122
    Points
    122
    Par défaut
    Je suis d'accord pour dire qu'il nous manque la déclaration de ce qu'est un T_statesVector.
    Par ailleurs, j'ai l'impression qu'il manque le 2eme paramètre en ce qui concerna ton appel au constructeur.
    "Toujours en faire plus pour en faire moins"

  4. #4
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Oui tout à fait j'ai dit n'importe quoi. Je devais pas être réveillé...

    std::vector<State<Type,Label>*> voici le type de statesVector (d'où le nom (en même temps ça pouvait ce deviner))

    Le problème s'est décalé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        template<typename Type,typename Label>
        Transition<Type,Label>* State<Type, Label>::GetTransitionByName(const Label& name)
        {
            for ( auto t : transitionsMap )// de type std::map< Transition<Type,Label>*, State<Type,Label>* > 
                if (t.first->GetName() == name)
                    return t.first;
     
            return nullptr;
        }
    gdb
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Starting program: C:\Program Files (x86)\CodeBlocks\Projets\FAST\a.exe
    [New Thread 680.0xe54]
    ->Etat Initial(testtouche haut) ->
    Etat 2(touche gauche) ->
    Etat 4(touche bas) ->
    (
    Program received signal SIGSEGV, Segmentation fault.
    0x000000000041c81a in FAST::State<std::string, std::string>::GetTransitionByName(std::string const&) ()
    (gdb) bt
    #0  0x000000000041c81a in FAST::State<std::string, std::string>::GetTransitionByName(std::string const&) ()
    #1  0x0000000000403f97 in FAST::Sample::TestBuilder::Sequence1() ()
    #2  0x0000000000000000 in ?? ()
    (gdb)
    J'ai modifié le premier post pour vous mettre la méthode Sequence au complet
    Nullius in verba

  5. #5
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Je suis désolé de double poster, mais là j'ai cerné le problème et je penses que ça va aller très vite pour vous que de me dire quelle copie j'ai raté

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        template<typename Type, typename Label>
        void Automaton<Type,Label>::UpdateState(Transition<Type,Label>* transition)
        {
            if (up_currentState->GetTransitionByName(transition->GetName()) != nullptr)
                up_currentState = std::unique_ptr<State<Type, Label>>(up_currentState->GetStateReachedByTransition(transition->GetName()));
        }
    l'affectation fait que up_currentState est nulle...elle fonctionne pendant 3 à 4 tours de boucle et après...boom ça explose... je tiens à préciser qu'au moment où ça explose je repasse dans un état que j'avais déjà rencontré...

    attendez je crois que je vois le problème...je créé des instances accessible uniquement par ce pointeur, mais ce que je n'avait pas compris, c'est qu'en faisant cette affectation je ne détruit jamais l'ancien pointeur...

    vous pouvez tout de même me confirmer (en me donnant une explication pointue sur ce type de smart pointer svp ) ?

    merci d'avance !

    edit : est-ce que la move semantic pourrait résoudre mon problème ?
    Nullius in verba

  6. #6
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    attendez je crois que je vois le problème...je créé des instances accessible uniquement par ce pointeur, mais ce que je n'avait pas compris, c'est qu'en faisant cette affectation je ne détruit jamais l'ancien pointeur...
    En effet le problème vient probablement de là dans ce cas.
    Un unique_ptr qui se fait réaffecter détruit d'abord l'ancien pointeur (pour éviter une fuite mémoire) avant de capturer le nouveau, c'est à dire qu'une fois ce code exécuté:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    C* c1 = new C();
    C* c2 = new C();
    std::unique_ptr<C> u = std::unique_ptr<C>(c1);
    u = std::unique_ptr<C>(c2);
    c1 n'est *plus* valide, il a été deleté.

  7. #7
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Citation Envoyé par Arzar Voir le message
    En effet le problème vient probablement de là dans ce cas.
    Un unique_ptr qui se fait réaffecter détruit d'abord l'ancien pointeur (pour éviter une fuite mémoire) avant de capturer le nouveau, c'est à dire qu'une fois ce code exécuté:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    C* c1 = new C();
    C* c2 = new C();
    std::unique_ptr<C> u = std::unique_ptr<C>(c1);
    u = std::unique_ptr<C>(c2);
    c1 n'est *plus* valide, il a été deleté.
    le contenu est détruit en même temps que le pointeur c'est ça ? rahhh je suis trop bête d'avoir mis aussi longtemps à réagir.

    Merci pour l'info en tout cas...

    euh dernière question... z'auriez pas une p'tite doc m'sieur ?
    Nullius in verba

Discussions similaires

  1. Débutant avec un livre usagé
    Par wreaghea dans le forum Langage
    Réponses: 3
    Dernier message: 31/08/2006, 10h05
  2. pb de débutant avec un tableau
    Par nielsou dans le forum C++
    Réponses: 5
    Dernier message: 09/06/2006, 16h15
  3. [C#][service windows] problème de débutant avec 1 timer
    Par Nycos62 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 14/10/2005, 11h22
  4. [Delphi 2005] Débutant avec problème de création de fichier
    Par Patcdc dans le forum Bases de données
    Réponses: 2
    Dernier message: 06/06/2005, 18h41
  5. probleme de débutant avec D3DXVECTOR3
    Par airseb dans le forum DirectX
    Réponses: 6
    Dernier message: 16/08/2003, 21h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo