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 :

problème d'allocation d'auto_ptr


Sujet :

C++

  1. #1
    Membre régulier Avatar de Linu6
    Profil pro
    Inscrit en
    Août 2007
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 227
    Points : 106
    Points
    106
    Par défaut problème d'allocation d'auto_ptr
    voici le code qui est la cause de mes maux de tête .. depuis 3 jours.

    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
    #include <fstream>
    #include <iostream>
    #include <memory>
    using namespace std;
     
    class file_error {};
     
    class entier_f {
    private:
      int * a;
      char * fn;
      ifstream input;
     
    public:
      entier_f(char * nom, int val=0) : fn(nom) {
        a = new int[1000000];	// Allocation d'un tableau de 1 Mo !!!
        *a= val;
        input.open(fn);
        if (! input) { 
          throw(file_error());
        };
      };
      ~entier_f() {
        delete a;
        a=NULL;
        input.close();
      };
    };
     
    class entier_f1 {
    private:
      auto_ptr<int> a;
      char * fn;
      ifstream input;
     
    public:
      entier_f1(char * nom, int val=0) : fn(nom) {
        a = new int[1000000];	// Allocation d'un tableau de 1 Mo !!!
        *a= val;
        input.open(fn);
        if (! input) { 
          throw(file_error());
        };
      };
      ~entier_f1() {
        input.close();
      };
    };
     
    main() {
      try {
        entier_f I2("toto");
      } 
      catch(file_error) {
        cout << "erreur de lecture de fichier" << endl;
      };
     
      int j=0;
      for (int i=0;i<100;i++) {	
        j++;
        try {
          entier_f1 I2("toto");
        } catch (file_error) {
          //      cout << "ERR" << endl;
          continue;
        } catch (...) {
          break;                 // Pas de fuite de memoire
        };
      };
      cout << "boucle executee " << j << " fois" << endl; 
     
      j=0;
      for (int i=0;i<100;i++) {	
        j++;
        try {
          entier_f I2("toto");
        } catch (file_error) {
          //      cout << "ERR" << endl;
          continue;
        } catch (...) {
          break;                 // ca va planter (fuite de memoire)
        };
      };
      cout << "boucle executee " << j << " fois" << endl;
    };

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Et c'est quoi le problème ? compilation, exécution, crash, ...
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Salut,

    Bon alors plusieurs remarques :
    1) ton code ne compile pas (c'est quand même gênant)
    2) le prototype de la fonction main c'est :
    ou bien :
    3) tu convertis des char const * en char * : c'est moche.

    Bon ceci dit le problème vient du fait que le destructeur de auto_ptr fait un delete sur le pointeur qu'il gère. Or toi tu lui passes un tableau et je te rappelle que dans ce cas la libération de la mémoire doit se faire avec un delete[]. Ton programme a un comportement indéterminé.

    PS : si tu es sous Linux un outil comme valgrind permet de détecter ce genre de problème.

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Chaque fois que j'ai utilisé l'opérateur = pour initialiser un auto_ptr<> à partir d'un pointeur brut, j'ai eu des problèmes (sous Visual).
    Je conseille d'utiliser sa fonction membre reset() à la place.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce code marche sous Visual 2005, avec un fichier "toto" vide :
    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
    //problème d'allocation d'auto_ptr
    // par Linu6
    //http://www.developpez.net/forums/showthread.php?p=3396870#post3396870
     
    #include <fstream>
    #include <iostream>
    #include <memory>
    #include <exception>
    #include <string>
    using namespace std;
     
    class file_error : public std::exception
    {
    public:
    	//NOTE: Ceci marche sous Visual car le constructeur
    	//qui prend seulement un char const * en paramètre est garanti dupliquer la chaîne.
    	//Le code risque de devoir être modifié sous d'autres compilos,
    	//car je ne sais pas ce que dit le standard sur le(s) constructeur(s) de std::exception
    	file_error(char const *fileName)
    	 : std::exception(std::string("File error (").append(fileName).append(")").c_str())
    	{ }
    };
     
    class entier_f {
    private:
    	int * a; //Lifetime managed by this
    	char const * fn; //Lifetime NOT managed by this
    	ifstream input;
     
    public:
    	entier_f(char const * nom, int val=0) : fn(nom) {
    		a = new int[1000000];	// Allocation d'un tableau de 1 Mo !!!
    		a[0] = val;
    		input.open(fn);
    		if (!input) { 
    			throw(file_error(nom));
    		};
    	};
    	~entier_f() {
    		delete[] a;
    		a=NULL;
    		input.close();
    	};
    };
     
     
    class entier_f1 {
    private:
    	auto_ptr<int> a;
    	char const * fn; //Lifetime NOT managed by this
    	ifstream input;
     
    public:
    	entier_f1(char const * nom, int val=0) : fn(nom) {
    		a.reset(new int[1000000]);	// Allocation d'un tableau de 1 Mo !!!
    		a.get()[0] = val; //J'emploie la syntaxe tableau, puisque c'est sur un tableau qu'on pointe
    		input.open(fn);
    		if (!input) { 
    			throw(file_error(fn));
    		};
    	};
    	~entier_f1() {
    		input.close();
    	};
    };
     
     
    int main(void) {
    	try {
    		entier_f I2("toto");
    	} 
    	catch(exception const &e) {
    		cout << "erreur de lecture de fichier: " << e.what() << endl;
    	};
     
    	int j=0;
    	for (int i=0;i<100;i++) {	
    		j++;
    		try {
    			entier_f1 I2("toto");
    		} catch (exception const &) {
    			//      cout << "ERR" << endl;
    			continue;
    		} catch (...) {
    			break;                 // Pas de fuite de memoire
    		};
    	};
    	cout << "boucle executee " << j << " fois" << endl; 
     
    	j=0;
    	for (int i=0;i<100;i++) {	
    		j++;
    		try {
    			entier_f I2("toto");
    		} catch (file_error) {
    			//      cout << "ERR" << endl;
    			continue;
    		} catch (...) {
    			break;                 // ca va planter (fuite de memoire)
    		};
    	};
    	cout << "boucle executee " << j << " fois" << endl;
    	return 0;
    };
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre régulier Avatar de Linu6
    Profil pro
    Inscrit en
    Août 2007
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 227
    Points : 106
    Points
    106
    Par défaut
    re

    Pardon, pour avoir oublié de mentionner quelques détails.
    Ainsi: En ce moment je travaille sous Windows (et non linux)
    ensuite le problème est un problème de compilation. qui se trouve dans

    class entier_f1 -> public: -> allocation (Ligne2)
    et voici le message d'erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     In constructor `entier_f1::entier_f1(char*, int)': 
    no match for 'operator=' in '((entier_f1*)this)->entier_f1::a = (int*)operator new [](4000000u)' 
    \include\c++\3.4.2\memory:223 candidates are: std::auto_ptr<_Tp>& std::auto_ptr<_Tp>::operator=(std::auto_ptr<_Tp>&) [with _Tp = int] 
    include\c++\3.4.2\memory:223    
    std::auto_ptr<_Tp>& std::auto_ptr<_Tp>::operator=(std::auto_ptr_ref<_Tp>) [with _Tp = int]

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    As-tu lu les messages de Médinoc et mon post ?

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    @Montag: En effet, je n'ai pas pris en compte ton post dans mon code.
    Sous l'implémentation Microsoft actuelle, ça marche parce que int n'a pas de destructeur, mais ce n'est absolument pas garanti marcher.

    En pratique, on peut dire que gérer un tableau avec auto_ptr<> est impossible. C'est sans doute pour ça qu'existe la classe vector<>...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre régulier Avatar de Linu6
    Profil pro
    Inscrit en
    Août 2007
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 227
    Points : 106
    Points
    106
    Par défaut
    re

    une dernière question (histoire de compléter le topic )
    Comment on détruit un tableau alloué avec reset()?

    merci.

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    reset() n'alloue rien, il sert juste à affecter un pointeur brut à un auto_ptr<>.

    Comme Montag l'a dit, auto_ptr<> n'offre aucun moyen de désallouer proprement un tableau: Tu ne peux désallouer qu'un seul objet avec.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre régulier Avatar de Linu6
    Profil pro
    Inscrit en
    Août 2007
    Messages
    227
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 227
    Points : 106
    Points
    106
    Par défaut
    ok

    merci à vous.

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

Discussions similaires

  1. Problème d'allocator
    Par Quark-Up dans le forum C++
    Réponses: 4
    Dernier message: 23/03/2006, 01h37
  2. Problème d'allocation mémoire
    Par cali1983 dans le forum C++
    Réponses: 10
    Dernier message: 10/03/2006, 23h23
  3. Problème d'allocation de mémoire dans la pile
    Par prophet666 dans le forum x86 32-bits / 64-bits
    Réponses: 6
    Dernier message: 19/01/2006, 02h22
  4. fenetre MDI - problème d'allocation
    Par say dans le forum C++Builder
    Réponses: 8
    Dernier message: 03/11/2005, 17h06
  5. Question sur les problèmes d'allocation dynamique
    Par slylafone dans le forum C++
    Réponses: 23
    Dernier message: 25/10/2004, 14h18

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