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 :

Impossible de faire un delete dans un destructeur


Sujet :

C++

  1. #1
    Membre éprouvé Avatar de gnto
    Homme Profil pro
    Ingénieur système logiciel
    Inscrit en
    Janvier 2006
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur système logiciel
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2006
    Messages : 923
    Points : 1 210
    Points
    1 210
    Par défaut Impossible de faire un delete dans un destructeur
    bonjour,

    on va faire simple

    etrex.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
     
    #pragma warning(disable:4786)
     
    #include <iostream>
    #include "nmea.hpp"
    #include "error.hpp"
     
    using namespace std;
     
    int main(int argc, char **argv)
    {
     
    	nmea n(13);
     
    	return 0;
    }
    nmea.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
    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
     
     
     
    #ifndef NMEA_HPP_
    #define NMEA_HPP_
     
    #include <string>
    #include <vector>
    #include <iostream>
     
    #include "serie.hpp"
     
    #define NMEA_GARMIN "PG"
    #define NMEA_STD "GP"
    #define NMEA_COMPASS "HC"
     
     
    using namespace std;
     
     
    class nmea
    {
    private :
    	vector<string> trames;
    	serie *S;
    	int nbr_trame;
     
    	/*method private*/
     
    	/*compute cheksum*/
    	bool checksum(string trame);
     
    	/*verify if the trame is good*/
    	bool verify_trame(string trame);
     
    public : 
     
    	nmea(int nb_trame);
    	~nmea();
    	bool add_trame(string trame);
    	void read_gps();
    	void analyse();
     
     
    };
     
     
    #endif
    nmea.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
     
     
    #pragma warning(disable:4786)
     
    #include "nmea.hpp"
    #include <iostream>
     
    nmea::nmea (int nb_trame)
    {
    	try
    	{
    		S = new serie ("COM1", 4800, 0, 8, 0, 0);
    	}
    	catch (error e)
    	{
    		e.run ();
    	}
     
    	nbr_trame = nb_trame;
    }
     
    ...
     
    nmea::~nmea ()
    {
    	delete S;
    }
    serie.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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
     
    #ifndef SERIE_HPP_
    #define SERIE_HPP_
     
    #include <string>
    #include <windows.h>
    #include "error.hpp"
    using namespace std;
     
     
    class serie
    {
    private:
     
    	HANDLE m_h;
     
    public:
     
    	serie(string path, int speed, int parity, int nbrBits, int stopBits,
    		int fluxCtrl );
    	~serie();
     
    	char get_Byte();
    	string get_line();
    };
     
    #endif // SERIE_HPP_
    serie.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
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
     
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <fstream>
     
    #include "error.hpp"
    #include "serie.hpp"
     
    using namespace std;
     
     
    serie::serie(string path, int speed, int parity, int nbrBits, int stopBits,
    			 int fluxCtrl)
    {
    	BOOL res;
    	DCB dcb = {0};
     
    	serie::m_h = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE,
    		0, // no sharing
    		0, // can't inherit this handle
    		OPEN_EXISTING,
    		FILE_FLAG_OVERLAPPED,
    		0);
    	if (serie::m_h== INVALID_HANDLE_VALUE)
    		 throw error::error("Impossible d'ouvrir le port serie",-10);
     
    	if (!GetCommState(serie::m_h, &dcb))
    		throw error::error("Ne peut pas recuperer les options du port serie ",-11);
     
    		/*remise a zero du device control block*/
    		memset(&dcb, 0, sizeof(dcb));
     
    		/*configuration de la connection*/
    		dcb.DCBlength = sizeof(dcb);		
    		dcb.BaudRate = speed; // speed, 4800 bps for NMAE 187
    		dcb.fBinary = TRUE; // because the win32 docs say so
    		dcb.fParity = (parity==0);
    		/*a gerer */
    		dcb.fDtrControl = DTR_CONTROL_DISABLE;
    		dcb.fRtsControl = RTS_CONTROL_DISABLE;
    		dcb.ByteSize = nbrBits; // char size -- 8 bits
    		dcb.Parity =parity; // parity 
    		dcb.StopBits = stopBits;
     
    		// set the new options
    		res = SetCommState(m_h, &dcb);
     
    		if (!res)
    			throw error::error("Ne peut pas mettre les options du port serie ",-12);
    		COMMTIMEOUTS timeouts;
    		memset(&timeouts, 0, sizeof(timeouts));
    		timeouts.ReadIntervalTimeout = MAXDWORD;
    		timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
    		timeouts.ReadTotalTimeoutConstant = 1300;
     
    		res = SetCommTimeouts(m_h, &timeouts);
    		if (!res)
    			throw error::error("Ne peut pas configurer le timeout du port serie",-13);
     
    		 res = SetupComm(m_h, 1200,1200);
    		if (!res)
    			throw error::error("Ne peut pas initialiser le port serie ",-14);
     
     
     
    }
     
     
    char serie::get_Byte()
    {
    	char c;
      DWORD num_read = 0;
      OVERLAPPED ol;
      memset(&ol, 0, sizeof(ol));
    HANDLE hd;
     
      hd = CreateEvent(NULL, TRUE, FALSE, NULL);
      if (hd == 0) 
    	  throw error::error("Impossible d'obtenir un event ",-15);
      ol.hEvent = hd;
     
      BOOL res = ReadFile(m_h, &c, 1, &num_read, &ol);
      if (!res && GetLastError() != ERROR_IO_PENDING)
        throw error::error("Ne peut pas lire les données sur le port serie ",-16);
      else if (!res) {
        // read waiting to finish
        res = WaitForSingleObject(ol.hEvent, 1300);
        switch (res) {
        case WAIT_TIMEOUT:
          throw error::error("Le timeout est depasse",-17);
          break;
        case WAIT_OBJECT_0:
          res = GetOverlappedResult(m_h, &ol, &num_read, FALSE);       
          break;
        default:
          throw error::error("N'a pas pu lire durant le temps imparti ",-18);
        }
      }
      else
        // fall through and check num_read
     
      if (num_read != 1)
        std::cout << "error" << std::endl;
     
      return c;
    }
     
    string serie::get_line()
    {
    	char c;
    	string trame ="";
    	while((c = get_Byte())!='\n')
    			trame += c;
    	return trame;
    }
     
     
     
    serie::~serie()
    {
    	if(CloseHandle(m_h)!=0)
    		throw error::error("N'a pas pu fermer la communication avec la liaison serie",-19);
    	cout << "close"<<endl;
    }

    Donc je n'ai aucun probleme de compilation ni d'édition mais plutôt une erreur quand le programme essaie de faire le delete (nmea.cpp) à l'execution

    je compile avec MSVC++ 6.0

    merci d'avance.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Il est *possible* que le delete sur un pointeur NULL pose problème... normalement, ca ne devrait pas... mais avec VC++ 6.0, on ne sait jamais( )

    Ce que tu *peux* toujours faire pour contourner le problème, c'est de mettre le delete dans un test du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    nmea::~nmea ()
    {
        if(S!=NULL)
    	delete S;
    }

  3. #3
    Membre éprouvé Avatar de gnto
    Homme Profil pro
    Ingénieur système logiciel
    Inscrit en
    Janvier 2006
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur système logiciel
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2006
    Messages : 923
    Points : 1 210
    Points
    1 210
    Par défaut
    je te remercie de ta réponse mais le probleme que j'aurais du voir avant de poser cette question, c'est que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    serie::~serie()
    {
    	if(CloseHandle(m_h)!=0)
    		throw error::error("N'a pas pu fermer la communication avec la liaison serie",-19);
    }
    le destructeur renvoie un exception en cas d'erreur de CloseHandle() or je n'ai pas intercepté l'exception quand je fais le delete.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    nmea::~nmea ()
    {
        try
        {
    	delete S;
        }
        catch(error e)
        {
            throw e;
        }
    }

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Ouh là là!!
    On ne lance jamais d'exception dans un destructeur !

  5. #5
    Membre éprouvé Avatar de gnto
    Homme Profil pro
    Ingénieur système logiciel
    Inscrit en
    Janvier 2006
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur système logiciel
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2006
    Messages : 923
    Points : 1 210
    Points
    1 210
    Par défaut
    Citation Envoyé par Médinoc
    Ouh là là!!
    On ne lance jamais d'exception dans un destructeur !
    C'est bien beau, la théorie mais faire un close dans un destructeur c'est souvent les exemples que l'on nous montre.
    Alors si le close génere une erreur je ne vois pas comment faire à part cette solution ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    serie::~serie()
    {
    	if(CloseHandle(m_h)!=0)
    		throw error::error("N'a pas pu fermer la communication avec la liaison serie",-19);
    }

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    C'est vrai que c'est assez délicat, mais ça n'empêche pas qu'un destructeur pareil peut transformer une exception en une autre, effaçant toute trace de la première...

    Et puis, CloseHandle() n'est pas vraiment supposé échouer, à moins qu'on lui passe un handle invalide (donc, impossible à fermer de toute façon).
    D'ailleurs, free() retourne void, par exemple.
    Donc, je ne sais pas s'il est vraiment possible de rattrapper cette erreur.

    Mais si tu penses que cette erreur est prioritaire sur toute autre exception pouvant être lancée tant que cet objet existe, je pense que tu peux laisser ton throw...

  7. #7
    Membre éprouvé Avatar de gnto
    Homme Profil pro
    Ingénieur système logiciel
    Inscrit en
    Janvier 2006
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur système logiciel
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2006
    Messages : 923
    Points : 1 210
    Points
    1 210
    Par défaut
    Citation Envoyé par Médinoc
    C'est vrai que c'est assez délicat, mais ça n'empêche pas qu'un destructeur pareil peut transformer une exception en une autre, effaçant toute trace de la première...
    C'est pire que ça !!! ça masque l'erreur puisque je n'ai eut qu'une erreur à l'execution vu que n'intercepté pas l'exception et qu'il m'en génerer une !

    Citation Envoyé par Médinoc
    Et puis, CloseHandle() n'est pas vraiment supposé échouer, à moins qu'on lui passe un handle invalide (donc, impossible à fermer de toute façon).
    D'ailleurs, free() retourne void, par exemple.
    Donc, je ne sais pas s'il est vraiment possible de rattrapper cette erreur.
    http://msdn2.microsoft.com/en-us/library/ms724211.aspx
    Citation Envoyé par Médinoc
    Mais si tu penses que cette erreur est prioritaire sur toute autre exception pouvant être lancée tant que cet objet existe, je pense que tu peux laisser ton throw...
    Ce n'est pas vraiment une question de priorité d'exception mais de rigueur.
    je traite toutes les erreurs avec les exceptions en C++. Surtout s'il y a une possible erreur, voir la valeur de retour du closehandle.

    J'en conviens c'est ici assez maladroit.

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Ben oui.
    Si serie est une classe RAII, CloseHandle() n'a pas de raison d'échouer, sauf si l'ouverture a foiré dans le constructeur (puisque tu ne testes pas le hhandle avant de le fermer).

    Ce n'est pas vraiment une question de priorité d'exception mais de rigueur.
    je traite toutes les erreurs avec les exceptions en C++. Surtout s'il y a une possible erreur, voir la valeur de retour du closehandle.

    J'en conviens c'est ici assez maladroit.
    Ben si, puisque ça masque une erreur, on ne peut se permettre de faire ça si l'on n'estime pas que l'erreur masquante vaut la peine de masquer toutes les autres.

    D'un autre coté, puisque CloseHandle() n'est pas supposé échouer (si tu rajoutes un test avant), on peut considérer une erreur de CloseHandle() comme suffisamment exceptionnelle pour mériter une attention immédiate, donc prioritaire.

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

Discussions similaires

  1. Impossible de faire un Onunload dans un fichier du disque
    Par msoldano dans le forum Informix
    Réponses: 6
    Dernier message: 15/09/2009, 12h47
  2. Impossible de faire le tri dans un sous état
    Par Oliv'83 dans le forum IHM
    Réponses: 3
    Dernier message: 25/03/2008, 18h39
  3. Réponses: 5
    Dernier message: 17/10/2007, 18h17
  4. Réponses: 3
    Dernier message: 23/03/2007, 07h54
  5. probleme de delete dans un destructeur
    Par Chewbi dans le forum C++
    Réponses: 6
    Dernier message: 12/03/2006, 00h29

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