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 de mémoire


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 6
    Par défaut problème d'allocation de mémoire
    Salut Tlm,

    J'ai un petit probleme d'allocation de memoire je pense.
    J'ai beaucoup de mal a l'identifier.

    je peux creer des grilles de taille 4 et plus mais pas de taille 2 ou 3....

    qqun peut il m'eclairer svp

    merci bcp

    --------------------------------------------------------------------------

    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
    #ifndef GRILLE_HPP
    #define GRILLE_HPP
     
    class Grille {
     
          public:
                 Grille(int dim);
                 Grille(Grille &g);
                 ~Grille();
                 int getDimension();
                 int getValeur(int x, int y);
                 bool ligneEstVide(int x);
                 bool colonneEstVide(int y);
                 void ViderPosition(int x, int y);
                 void afficher();
     
          private:
                 int dimension;
                 int** tabValeurs;
     
    };
     
    #endif
    --------------------------------------------------------------------------

    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
    #include "Grille.hpp"
    #include <iomanip>
    #include <iostream>
     
    using namespace std;
     
    Grille :: Grille(int dim) {
        tabValeurs = new int * [dimension = dim];
        for (int i = 0; i < dimension ; i++){
            tabValeurs[i] = new int [dimension];
            for (int j = 0; j < dimension; j++){
                tabValeurs[i][j] = 0;
            }
        }
    }
     
    Grille :: Grille(Grille &g) {
        tabValeurs = new int * [g.dimension];
        for (int i=0;i<g.dimension;i++){
            tabValeurs[i] = new int [g.dimension];
            for (int j = 0;j < g.dimension; j++){
                tabValeurs[i][j] = g.tabValeurs[i][j];
            }
        }
    }
     
    Grille :: ~Grille() {
        delete tabValeurs;
    }
     
    int Grille :: getDimension(){
        return dimension;
    }
     
    int Grille :: getValeur(int x, int y){
        return tabValeurs[x][y];
    }
     
    bool Grille :: ligneEstVide(int x){
         for (int i = 0;i<dimension;i++){
             if (tabValeurs[x][i]!=1111){
                return false;
             }
         }
         return true;
    }
     
    bool Grille :: colonneEstVide(int y){
         for (int i = 0;i<dimension;i++){
             if (tabValeurs[i][y]!=1111){
                return false;
             }
         }
         return true;
    }
     
    void Grille :: ViderPosition(int noLigne, int noColonne) {
         tabValeurs[noLigne][noColonne] = 1111;
    }
     
    void Grille :: afficher(){
    	for ( int i = 0; i < dimension; ++i ) {
    		for ( int j = 0 ; j < dimension; ++j ) {
    			cout << "|";
                cout << setw(3) << tabValeurs[i][j];
                cout << " |";
    		}
    		cout << endl << endl;
    	}
    }
    --------------------------------------------------------------------------
    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
     
        //Grille grille(2);
        //Grille grille1(3);
        Grille grille2(4);
        Grille grille3(5);
        Grille grille4(6);
        Grille grille5(7);
        Grille grille6(8);
        //cout<<grille.getDimension()<<endl;
        //cout<<grille.getValeur(2,2)<<endl;
        //cout<<grille.getValeur(3,3)<<endl;
        //cout<<grille.getValeur(1,1)<<endl;
        grille6.afficher();
        grille5.afficher();
        grille4.afficher();
        grille3.afficher();
        grille2.afficher();
        //grille1.afficher();
        //grille.afficher();
    --------------------------------------------------------------------------

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Salut, et bienvenue sur le forum.

    Quelques remarques préliminaires:
    1. Il est peu recommandé de faire deux choses à la fois, surtout s'il s'agit d'allouer de la mémoire pour un membre et d'en initialiser un autre
    2. Il est des plus intéressant d'utiliser les listes d'initialisation dans le constructeur
    3. Si tu crées une boucle pour allouer dynamiquement de la mémoire, il te faut une boucle pour libérer correctement toute la mémoire
    4. Sais tu qu'il n'y a rien de plus proche d'un tableau à deux dimensions qu'un tableau à une seule si tu reste dans des dimensions raisonables (je dirais > à 1000*1000), cela peut te faciliter la vie

    Dans l'ordre, cela signifie que, dans le constructeur, la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tabValeurs = new int * [dimension = dim];
    est une véritable horreur pour les yeux (après trois jours sans avoir touché à ce code, je te mets au défis de te rappeler tout de suite que tu initialise dimention au passage )
    et serait avantageusement remplacée, au pire, par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dimention=dim;
    tabValeurs = new int *[dimention];
    Mais, la deuxième remarque aidant, on préférera carrément un code ressemblant à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Grille::Grille (int dim):dimention(dim)
    {
        tabValeurs = new int *[dimention];
        /*...*/
    }
    La remarque en [3] est motivée par le destructeur:

    Lorsque, après avoir fait un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    tabValeurs = new int *[dimention];
    for (int i = 0; i < dimension ; i++)
    {
            tabValeurs[i] = new int [dimension];
    }
    tu te contente d'un
    cela ne provoque absolument pas la libération de la mémoire qui avait été allouée pour tabValeurs[0] à tabValeurs[dimention]...

    Ce phénomène s'appelle les "fuites mémoire" (memory leaks en anglais), et fait que, plus tu créera et détruira des objets du type concerné (ici grille), plus tu te retrouvera avec une quantité importante de mémoire que le système considère comme utilisée par l'application, mais à laquelle on n'a plus aucun moyen d'accéder

    A la longue, cela peut entraîner un tas de problèmes, allant du simple ralentissement au plantage pur et simple de l'application (si pas du système complet), et il vaut donc mieux éviter d'en arriver là

    Pour éviter le problème, le destructeur devrait ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Grille ::~Grille()
    {
        for(int i=0;i<dimention;i++)
            delete[] tabValeurs[i];
        delete[] tabValeurs;
    }
    Et cela nous emmène tout droit à la remarque [4]...

    Etant donné qu'il est très facile d'oublier de libérer la deuxième dimension avant de libérer la première, et que, de toutes manière, la mémoire ne se présente quand même que sous la forme d'un tableau à une dimension, on peut se baser sur le fait qu'une grille de X lignes et de Y colonnes n'est jamais qu'une "représentation visuelle" de X*Y cellules

    L'avantage étant que l'on peut alors demander l'allocation dynamique de toute la mémoire ne une seule fois sous la forme générique de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type* tab = new type[X*Y];
    et bien évidemment la libération de la mémoire en une seule fois aussi sous la forme de
    L'inconvénient principal réside dans le fait... qu'on court beaucoup plus de risques - si le nombre de lignes et de colonnes est important - que le système ne trouve plus autant de mémoire contiguë disponible...

    Mais bon, si cela peut t'inciter à gérer la mémoire en "bon père de famille", c'est un moindre mal

    Il reste le détail de la manière d'accéder aux différentes cellules à aborder avec cette optique, et, pour ne pas me lancer (encore une fois ) dans un roman, je me contenterai de te fournir la formule sous forme d'une petite fonction (explications sur demande)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    type Grille::GetCellule(int ligne, int colonne)
    {
        return tab[ligne*nbcolonne + colonne]
    }
    où nbcolonne est le nombre total de colonnes présentes dans la grille
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Et puis du coup...
    A vouloir tout faire d'un coup... on en oublie....

    Comme le constructeur par recopie qui n'initialise pas dimension...
    Et donc, devrait faire planter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Grille a(20);
    Grille b(a);
    Grille c(b);
    Et il manque aussi un opérateur d'affectation.

    Un code genre:
    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
     
    inline Grille::Grille(int dim) : m_dim(0), m_data(0)
    {
        set(dim,0);
    }
    inline Grille::Grille(const Grille& g) : m_dim(0), m_data(0)
    {
        set(g.m_dim,g.m_data);
    }
    inline Grille& operator=(const Grille& g)
    {
        if (&g != this) {
            reset();
            set(g.m_dim,g.m_data);
        }
        return *this;
    }
    inline Grille::~Grille(void)
    {
        reset();
    }
     
    void Grille::set(int dim, const int* data)
    {
        assert(m_data == 0); // juste histoire d'être sur
        if (dim > 0) {
            size_t size = dim * dim;
            m_data = new int [size];
            if (m_data) {
               if (data)
                   memcpy(m_data,data,sizeof(int)*size);
               m_dim = dim;
            }
        }
    }
     
    void Grille::reset()
    {
        if (m_data) {
             delete [] m_data;
             m_data = 0;
        }
        m_dim = 0;
    }

Discussions similaires

  1. [2008] Problème d'allocation de mémoire
    Par help26 dans le forum SSIS
    Réponses: 2
    Dernier message: 07/06/2012, 14h03
  2. Problème d'allocation de mémoire: Fatal error: Allowed memory
    Par Arget dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 09/09/2011, 07h55
  3. problème d'allocation de mémoire pour la JVM
    Par Sfaxiano dans le forum Général Java
    Réponses: 13
    Dernier message: 06/05/2010, 20h16
  4. problème d'allocation de mémoire
    Par kreel dans le forum C
    Réponses: 10
    Dernier message: 28/04/2007, 14h40
  5. 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

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