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 :

Programme crash à la sortie d'une méthode


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Points : 73
    Points
    73
    Par défaut Programme crash à la sortie d'une méthode
    Bonjour,

    Je viens du monde JAVA et je commence à me mettre sérieusement au C++ et donc je fais des exercices donnés par le prof en C++ au lieu de java pour m'habituer au langage(dont j'ai déjà la base).

    Ici le but est de faire un ensemble de int en se basant sur l'objet bitset.
    Tout à l'air de marcher mais quand j'emploie la méthode "BitSetOfShort::toString()" le programme crash en voulant en sortir.
    Avec le debugging j'ai vue que le crash arrive dans free.c qui sert à libérer la mémoire des pointeurs mais j'ai du mal à voire mon erreur.

    Voici mes classes :
    BitSetOfShort :
    H
    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
    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <limits.h>
    #include <bitset>
    #include <sstream>
    using namespace std;
     
    class BitSetOfShorts
    {	
    public:
    	BitSetOfShorts();
    	~BitSetOfShorts();
    	bool isEmpty();
    	int size();
    	void add(short e);
    	void remove(short e);
    	bool contains(short e);
    	void unionSets(BitSetOfShorts s);
    	void intersectionSets(BitSetOfShorts s);
    	string toString();
    	bitset<1+SHRT_MAX-SHRT_MIN> getBitset();
     
    	static int indexFromElt(short e);
    	static short eltFromIndex(int i);
     
    	static const short MIN = SHRT_MIN;
    	static const short MAX = SHRT_MAX;
    private :
    	bitset<1+SHRT_MAX-SHRT_MIN> b;
    };
    CPP
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    #ifndef BitSetOfShorts_h
    #define BitSetOfShorts_h
    #include "BitSetOfShorts.h"
    #endif
    #include "BitSetOfShortsItr.h"
     
    /* value : -X.... 0 .... +X */
    /* index :  0     X         */
     
    BitSetOfShorts::BitSetOfShorts(){}
     
    BitSetOfShorts::~BitSetOfShorts()
    {
    }
     
    int BitSetOfShorts::indexFromElt(short e)
    {
    	return e+1+MAX;
    }
     
    short BitSetOfShorts::eltFromIndex(int i)
    {
    	return i-1-MAX;
    }
     
    bool BitSetOfShorts::isEmpty()
    {
    	return b.none();
    }
     
    int BitSetOfShorts::size()
    {
    	return b.count();
    }
     
    void BitSetOfShorts::add(short e)
    {
    	b.set(e+1+MAX,true);
    }
     
    void BitSetOfShorts::remove(short e)
    {
    	b.set(e+1+MAX,false);
    }
     
    bool BitSetOfShorts::contains(short e)
    {
    	return b.at(e+1+MAX);
    }
     
    void BitSetOfShorts::unionSets(BitSetOfShorts s)
    {
    	size_t found;
    	string str = b.to_string();
    	found = str.find("1");
    	while(found!=string::npos)
    	{
    		b.set(eltFromIndex(-(static_cast<int>(found))-1),false);
    		found = str.find("1",found+1);
    	}
    }
     
    void BitSetOfShorts::intersectionSets(BitSetOfShorts s)
    {
    	size_t found;
    	string str = b.to_string();
    	found = str.find("1");
    	while(found!=string::npos)
    	{
    		if(!this->contains(found))
    		{
    			b.set(eltFromIndex(-(static_cast<int>(found))-1),false);
    		}
    		found = str.find("1",found+1);
    	}
    } 
     
    bitset<1+SHRT_MAX-SHRT_MIN> BitSetOfShorts::getBitset()
    {
    	return b;
    }
     
    string BitSetOfShorts::toString() { 
        stringstream r;
    	r<<"{";
        BitSetOfShortsItr itr(this);
    	if (isEmpty()) return ("{}");
        while (itr.hasMoreElements()){
    		r << ", " << itr.nextElement();
    		cout<<r.str()<<endl;
        }
    	r << "}";
    	itr.~BitSetOfShortsItr();
    	return r.str();
      }
    BitSetOfShortsItr (iterateur de l'ensemble) :
    H
    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
     
    #ifndef BitSetOfShorts_h
    #define BitSetOfShorts_h
    #include "BitSetOfShorts.h"
    #endif
     
    class BitSetOfShortsItr
    {
    public:
    	BitSetOfShortsItr(BitSetOfShorts* b);
    	~BitSetOfShortsItr();
     
    	bool hasMoreElements();
    	short nextElement();
    private:
    	BitSetOfShorts* b;
    	bitset<1+SHRT_MAX-SHRT_MIN> bitset;
    	int current;
    };
    CPP
    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
    #include "BitSetOfShortsItr.h"
     
    BitSetOfShortsItr::BitSetOfShortsItr(BitSetOfShorts* b2)
    {
    	b = b2;
    	bitset=b->getBitset();
    	current = -1;
    }
     
    BitSetOfShortsItr::~BitSetOfShortsItr()
    {delete b;
    ~bitset;}
     
    bool BitSetOfShortsItr::hasMoreElements()
    {
    	string::size_type found;
    	string str = bitset.to_string();
     
    	found = str.find("1", current+1);
     
    	if(found!=string::npos)
    		return true; 
    	else
    		return false;
    }
     
    //PRE : hasMoreNextElements == true
    short BitSetOfShortsItr::nextElement()
    {
    	string::size_type found;
    	string str = bitset.to_string();
    	found = str.find("1", current+1);
    	current = found;
    	return b->eltFromIndex(-(static_cast<int>(found))-1);
    }
    main.cpp :
    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
    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #ifndef BitSetOfShorts_h
    #define BitSetOfShorts_h
    #include "BitSetOfShorts.h"
    #endif
    #include "BitSetOfShortsItr.h"
     
    using namespace std;
     
    int main()
    {
        BitSetOfShorts a;
        BitSetOfShorts b;
        short ta[6] = {-3, 5, 6, -3, 9, 9};
        short tb[4] = {6, 7, -2, -3};
        int i;
        for (i=0; i<(sizeof(ta)/sizeof(short)); i++) {
    	a.add(ta[i]);
    	cout << a.toString() <<a.size() << endl;
        }
        for (i=0; i<sizeof(tb)/sizeof(short); i++) {
            b.add(tb[i]);
    	cout<<b.toString()<<b.size()<<endl;
        }
        a.unionSets(b);
        cout<<a.toString()<<a.size()<<endl;
     
        return 0;
    }
    Est-ce que vous pourriez m'aider ?

    Cordialement,

    rXp>!<

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 131
    Points : 33 074
    Points
    33 074
    Billets dans le blog
    4
    Par défaut
    Bonsoir,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    itr.~BitSetOfShortsItr();
    Pourquoi faire ça ?

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Points : 73
    Points
    73
    Par défaut
    Une fois un objet utilisé ne faudrait-il pas appeler son destructeur (pour nettoyer la mémoire) ? (et les pointeurs, delete pointeur)

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 131
    Points : 33 074
    Points
    33 074
    Billets dans le blog
    4
    Par défaut
    Non.
    S'il s'agit d'un pointeur alloué dynamiquement il faut faire un delete pour libérer la mémoire pointée.
    S'il s'agit d'un objet statique, il est supprimé dès qu'on sort de son scope.
    L'appel explicite du destructeur est très rare et clairement pas nécessaire ici.
    Le destructeur c'est juste une fonction particulière appelé quand l'objet est supprimée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    BitSetOfShortsItr::~BitSetOfShortsItr()
    {delete b;
    ~bitset;}
    Même chose ?
    D'abord, tu fais un delete sur un objet que tu récupères via le constructeur et non alloué toi-même. Est-ce vraiment la marche à suivre ?
    Ensuite, qu'est-ce donc que ce ~bitset ?! ~ est un opérateur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Avec le debugging j'ai vue que le crash arrive dans free.c qui sert à libérer la mémoire des pointeurs mais j'ai du mal à voire mon erreur.
    Libération multiple.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Points : 73
    Points
    73
    Par défaut
    Le ~bitset était un teste, excusez-moi pour cette ligne.
    Ensuite j'utilise un pointeur b dans l'itérateur, il n'est pas nécessaire de libérer la mémoire donc ? (car si j'enlève le delete b, le code passe)

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 131
    Points : 33 074
    Points
    33 074
    Billets dans le blog
    4
    Par défaut
    Tu devrais relire ton cours sur la partie pointeur, ainsi que si ton niveau le permet ce fil de discussion.

    Un pointeur n'a rien d'extraordinaire, et il n'a non plus aucune raison d'être systématiquement delete. Un pointeur c'est avant tout un allias.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int i;
    int* pi = &i;
    delete pi;
    Ce code est faux. Pourtant j'ai un pointeur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int* pi = new int;
    delete pi;
    Là c'est bon, toujours avec un pointeur.

    Le ~bitset était un teste, excusez-moi pour cette ligne.
    Tu n'as pas à t'excuser, seulement..
    Il n'y a aucune parenthèse, donc il ne s'agit pas d'une fonction.
    Qu'espérais-tu donc avec avec cette ligne ?!
    http://en.wikipedia.org/wiki/Bitwise_operation#NOT

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Points : 73
    Points
    73
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Tu devrais relire ton cours sur la partie pointeur, ainsi que si ton niveau le permet ce fil de discussion.

    Un pointeur n'a rien d'extraordinaire, et il n'a non plus aucune raison d'être systématiquement delete. Un pointeur c'est avant tout un allias.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int i;
    int* pi = &i;
    delete pi;
    Ce code est faux. Pourtant j'ai un pointeur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int* pi = new int;
    delete pi;
    Là c'est bon, toujours avec un pointeur.


    Tu n'as pas à t'excuser, seulement..
    Il n'y a aucune parenthèse, donc il ne s'agit pas d'une fonction.
    Qu'espérais-tu donc avec avec cette ligne ?!
    http://en.wikipedia.org/wiki/Bitwise_operation#NOT
    Alors merci pour l’éclaircissement et en cours on fait du java pas du C++ donc j'apprend avec les tutoriaux et autres articles(donc oui il est possible que je sois un peu à côté de la plaque).
    Je vois la différence et mon erreur
    Pour ce qui est du ~bitset c'est bête mais je voulais mettre la ligne dans le constructeur et en refaisant le constructeur et destructeur je l'ai mis au mauvais endroit

    Ah et puisque j'y suis j'ai une petite question sur le langage c++(éviter d'ouvrir un autre topic pour une question toute bête).
    Quand on emploie les templates (pour la généricité), est-on obligé de mettre le code qui emploie l'objet générique dans le .h et pas le cpp. ?

    Cordialement,

    rXp>!<

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 632
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 632
    Points : 30 711
    Points
    30 711
    Par défaut
    Salut,
    Citation Envoyé par rXpCH Voir le message
    Alors merci pour l’éclaircissement et en cours on fait du java pas du C++ donc j'apprend avec les tutoriaux et autres articles(donc oui il est possible que je sois un peu à côté de la plaque).
    Je vois la différence et mon erreur
    Pour ce qui est du ~bitset c'est bête mais je voulais mettre la ligne dans le constructeur et en refaisant le constructeur et destructeur je l'ai mis au mauvais endroit
    Quand on travaille sur des valeurs binaires, l'opérateur ~inverse l'ensemble des bits.

    Ainsi, la valeur binaire de ~000001111 devient elle 11110000

    Par contre, pour tous les autres types, le symbole ~ est le symbole du destructeur du type, et un destructeur, , n'est jamais appelé explicitement (il n'y a, en fait, qu'un cas dans lequel on appelle explicitement le destructeur : le new placement ).

    Le destructeur est automatiquement appelée par le compilateur :
    1. Quand on fait un delete (ou un delete[] ) sur un objet créé avec new (respectivement new[] )
    2. dés que l'on quitte la portée dans laquelle la variable a été appelée.

    Ah et puisque j'y suis j'ai une petite question sur le langage c++(éviter d'ouvrir un autre topic pour une question toute bête).
    Quand on emploie les templates (pour la généricité), est-on obligé de mettre le code qui emploie l'objet générique dans le .h et pas le cpp. ?

    Cordialement,

    rXp>!<
    Tu dois, en fait, faire en sorte que le code d'implémentation des fonctions template soit accessible aux endroits où tu invoques la fonction en question ou faire en sorte que le compilateur génère déjà le code binaire de la fonction correspondant au type que tu utilises.

    Le principe d'une fonction (ou d'une classe) template, c'est de se dire que l'on en sait pas "quel type de donnée" on va manipuler, mais que l'on sait, par contre, "comment on va les manipuler"

    Or, le compilateur a besoin de savoir "ce que l'on manipule" pour pouvoir générer le code binaire, ne serait-ce que parce qu'il doit connaitre la taille du type manipuler pour y arriver

    Il faut donc qu'il dispose du code d'implémentation au moment où il est en mesure de déterminer le type de la donnée manipulée

    On peut envisager trois cas de figures:

    • Soit (c'est souvent le plus facile), on définit la fonction directement dans le fichier d'en-tête, au moment de sa déclaration (dans le corps de la classe) ou juste après la classe en prenant soin de préciser que la fonction est inline
    • Soit on définit la fonction dans un fichier dont l'extension est libre (tpp, impl, voir en _impl.h / _impl.hpp) et l'on prend soin d'inclure ce fichier au plus tard dans tous les fichiers dans lequel la fonction est invoquée
    • soit on a recours à l'instanciation explicite du code pour les types de données dont on sait qu'ils seront utilisés
    Dans le troisième cas, il est possible de ne pas fournir le fichier d'implémentaiton à l'utilisateur, mais la classe (ou les fonctions) template ne pourra alors être utilisée que pour lesquels l'instanciation explicite a été effectuée (et résultera en une erreur d'édition de liens pour les autres)

    une pratique courante quand on veut séparer la déclaration et l'implémentation est de créer trois fichiers :
    un fichier de déclaration (MyTempClass_decl.hpp , par exemple qui contient la définition de la classe et la déclaration des fonction libres:
    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
    #ifndef MYTEMPCLASS_DECL_HPP
    #define MYTEMPCLASS_DECL.HPP
    template <typename T>
    class MyTempClass
    {
        public:
            void foo();
            void doSomething();
            /*...*/
        private:
            T member_;
            /* ...*/
    };
    template <typename T>
    void someStuf(T const & );
    # endif MYTEMPCLASS_DECL_HPP
    un fichier d'implémentation (par exemple MyTempClass.tpp ou MyTempClass_impl.hpp)
    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
     
    template <typename T>
    inline
    void MyTempClass<T>::foo()
    {
        /*...*/
    }
    template <typename T>
    inline
    void MyTempClass<T>::doSomething()
    {
        /*...*/
    }
    template <typename T>
    void someStuff(T const & arg)
    {
        /*...*/
    }
    (le premier fichier peut alors servir quand on n'a besoin que de la déclaration de la classe ou des fonction, le second servant quand on a besoins des fonctions effective
    Un troisième fichier (MyTempClass.hpp par exemple) qui inclus les deux premier de manières à permettre l'utilisation de la classe de manière classique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #ifndef MYTEMPCLASS_HPP
    #define MYTEMPCLASS_HPP
    #include <MyTempClass_decl.hpp>
    #include <MyTempClass_impl.hpp>
    #endif //MYTEMPCLASS_HPP
    La seule extension qu'il vaut mieux (uniquement par habitude) éviter pour le fichier d'implémentation est l'extension .cpp (et ses variantes), pour la simple et bonne raison que les gens sont habitués au fait qu'un fichier portant cette expression ne doit jamais être incluscar, a priori, c'est le fichier qui sera compilé (règle de la définition unique des fonctions )

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Crash à l'appel d'une méthode.
    Par Invité dans le forum Langage
    Réponses: 12
    Dernier message: 27/02/2015, 19h32
  2. Problème de référence à la sortie d'une méthode
    Par skini26 dans le forum Général Java
    Réponses: 7
    Dernier message: 12/06/2013, 18h40
  3. Réponses: 3
    Dernier message: 18/06/2007, 19h06
  4. Réponses: 2
    Dernier message: 29/12/2005, 11h25
  5. une méthode qui écrit dans la sortie html ?
    Par iubito dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 03/12/2003, 16h34

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