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 :

Fuite mémoire avec le HEAP et Priority Queue


Sujet :

C++

  1. #1
    Membre confirmé
    Inscrit en
    Février 2013
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 94
    Par défaut Fuite mémoire avec le HEAP et Priority Queue
    Bonjour à toutes et à tous,

    En préambule: je découvre le C++ et la priority_queue.

    J'ai besoin de recoder un tout petit bout de programme (l'algorithme de dijkstra) afin de calculer des distances dans un graphe. Plus précisément, je teste un grand nombre de graphes de tailles différentes et ce petit bout de programme est appelé pour chaque graphe. Plus précisément la structure de mon programme ressemble à ceci:
    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
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
    {
        /***********************************
         *DECLARATIONS AND INITS
         ***********************************/
        ...
     
        /*******************************
         * Gather Inputs and Outputs & Alloc structures:
         *******************************/
        ...
     
        //Then perform the search for inflow and outflow nodes (find requested distance):
        for(i=0; i < N; i++) {
            for(j=0; j < N; j++) {
                if(rand_idx[i] < j && rand_idx[i] != N-1) { //only read the upper triangular part and omit the last line.
                    const int cur_dis = dijkstra(rand_idx[i], j);
     
                    //mexPrintf("distance=%d\n", distance);
                    if(cur_dis >= distance) {
                        //assign outputs and returns:
                        //also correct for indexation between MATLAB & C
                        plhs[0] = mxCreateDoubleScalar(rand_idx[i] +1 ); //in
                        plhs[1] = mxCreateDoubleScalar(rand_idx[j] +1 ); //out
                        plhs[2] = mxCreateDoubleScalar(cur_dis); //fdistance
                        return;
                    }
                }
            }
       }
     
        //we browsed 'A' without finding the requested distance, thus assign '-1' to outputs 
        plhs[0] = mxCreateDoubleScalar(-1.0); //in
        plhs[1] = mxCreateDoubleScalar(-1.0); //out
        plhs[2] = mxCreateDoubleScalar(-1.0); //fdistance
    }
    J'appelle donc la fonction dijkstra() un grand nombre de fois, et je retourne mon résultat 'plhs' à MATLAB. Cette fonction compilée est appelée un grand nombre de fois pour des graphes différents. L'algorithme fonctionne, les solutions sont correctes. La fonction dijkstra() utilise une priority_queue en global, avec des structures simples, c'est à dire:
    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
    vector < vector <int> > graph;
    vector < vector <int> > weight;
    vector < int> cost;
    int N;
     
    struct cmp
    {
      bool operator()(const int &lhs, const int &rhs) const
      {
        return cost[lhs] > cost[rhs];
      }
    };
     
    int min(const int a, const int b)
    {
    	if(a<b)
    		return a;
    	return b;
    }
     
    priority_queue <int,vector<int>,cmp> pq;
     
    int dijkstra(const int from, const int to)
    {
    	vector <bool> visited(N, false);
    	visited[from] = true;
    	cost [from] = 0;
    	pq.push(from);
        while(!pq.empty() && !visited[to])
    	{
    		int current = pq.top();
    		pq.pop();
    		visited[current] = true;
    		for(int i=0;i<graph[current].size();i++)
    		{	
    			if(!visited[graph[current][i]])
    			{
    				cost[graph[current][i]] = min( cost[graph[current][i]] ,cost[current] + weight[current][i]);
    				pq.push(graph[current][i]);
    			}
    		}
    	}
    	return cost[to];
    }
    Après un grand nombre d'appel j'ai une erreur bad allocation(). Après avoir consulté mon ami Google je me suis penché sur l'utilisation de la RAM par le programme et il me semble que cette erreur est due à l'utilisation complète de la RAM (plus d'allocation possible). Je ne maitrise pas les questions de mémoire dans le stack ou dans le heap, mais je pense que c'est lié à ca. En fait initialement je ne pensais même pas avoir besoin de vider la mémoire (pas de new(), donc pas de delete()), mais il s'avère que si je ne le fait pas ca pompe toute la ram. J'ai donc ajouté un petit bout de code qui permet de résoudre le problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void clean_queue(void) {
        while(!pq.empty()) {
            pq.pop();
        }
    }
    c'est à dire que je dépile toute la queue à la fin de chaque utilisation de cette fonction. Ca fonctionne beaucoup mieux, plus de problème d'allocation, par contre le fait de dépiler à chaque fois que j'ai fini d'utiliser un graphe particulier c'est effroyablement lent, même sur des petits graphes. En fait c'est même plus sournois que ca: sur les premiers graphes (cad première itérations) ca fonctionne bien, puis ca ralentit progressivement jusqu'à devenir très (TRES) lent. Donc je pense que j'ai seulement déplacé le problème et que vider l'espace mémoire est très couteux.

    D'où ma question: quelle solution adopter dans ce cadre pour maintenir une gestion mémoire efficace?

    Merci!

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Pour supprimer les éléments, le plus simple est de reconstruire une nouvelle priority_queue: pq = std::priority_queue<....>(); qui va directement vider le vector interne plutôt que des appels à pop() qui possède une complexité non nulle (https://en.cppreference.com/w/cpp/co...rity_queue/pop).

    On perd par contre le buffeur d'allocation et push() va ré-allouer de la mémoire qu'elle possédait déjà avant. Cela peut être négligeable, mais une solution est d'hériter de priority_queue et d'implémenter une fonction clear() pour utiliser std::vector::clear() du conteneur interne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct MyPriotityQueue : std::priority_queue<....>
    {
        void clear()
        {
            c.clear();
        }
    };

  3. #3
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Il est tout de même bien étrange que cette méthode soit absente. Y'a-t-il un « rationale » à son omission de la bibliothèque standard ?

    Je me permets une remarque en rapport avec le titre du sujet : on cause plutôt de « fuite (de) mémoire » lorsque cette dernière ne peut être récupérée, c'est-à-dire que l'on a pas conservé les adresses des blocs alloués. Ici la perte n'est pas définitive, ton programme demande simplement trop de ressources en même temps.

  4. #4
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Pour vider une priority_queue on peut aussi utiliser le swap ou l'assignation avec une queue vide.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    jo_link_noir l'a mentionné : ce n'est pas équivalent à clear car le buffer interne devra être alloué à nouveau, en tout cas on n'impose pas à l'implémentation de le conserver.

  6. #6
    Membre confirmé
    Inscrit en
    Février 2013
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 94
    Par défaut
    Déjà, merci à tous pour vos commentaires!

    Alors j'ai regardé les solutions proposées, et voici quelques tests qui montrent (à minima) que je ne fais pas ca comme il faut

    Suggestion 1: le swap:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    priority_queue <int,vector<int>,cmp> pq, pq2;
     
    void clear( void )
    {
       swap( pq, pq2 );
    }
    Suggestion 2: le clear():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct mypq :public priority_queue<int,vector<int>,cmp> {
        void clear(){
            this->c.clear();
        }
    };
     
    mypq pq;
    Et les résultats sur 200 itérations successives (pas de multithreads) en figure. On voit que à chaque nouvelle itération le temps de calcul augmente pour le swap et le clear() mais pas pour matlab qui reste constant (il s'agit des temps de calculs cumulés sur une modeste bécane). Du coup je pense que je vide qu'une partie de la queue, ou il me manque quelque chose quelque part.
    Nom : cumsum.jpg
Affichages : 217
Taille : 33,6 Ko

    Aussi en PJ une autre figure avec le temps pour chaque itération successive. on voit que le swap vide tout mais pas systématiquement....
    Nom : raw_times.jpg
Affichages : 216
Taille : 46,1 Ko


    Merci d'avance pour vos commentaires!

  7. #7
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Le swap que tu fais n'est pas bon. Il faut lire la phrase jusqu'au bout, ton swap ne fait qu'échanger 2 queues, au lieu d'échanger la queue avec une queue vide.
    Quant au clear(), il devrait fonctionner mieux que cela. Peut être qu'un réservant une taille adéquate il serait plus optimum?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    priority_queue<int,vector<int>,cmp>  pq;
     
    void clear()
    {
       swap( pq , priority_queue<int,vector<int>,cmp>{} );
    }
    // ou
    void clear()
    {
       pq = priority_queue<int,vector<int>,cmp>{};
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct mypq :public priority_queue<int,vector<int>,cmp> {
        void clear(){
            size_t prevsize = c.size();
            c.clear();
            c.reserve( prevsize * 2u + 1u );
        }
    };
    mypq  pq;

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Tu pourrais poster un code minimal mais complet qui permette de reproduire le problème ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Membre confirmé
    Inscrit en
    Février 2013
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 94
    Par défaut
    Merci pour vos retours,
    J'ai essayé le swap et le clean proposés (désolé j'avais omis les () dans le priorityqueue), et ca me donne le même soucis (chaque itération est plus lente que la précédente), je vais essayer de poser un code minimal rapidement, ca demande un peu de temps car il faut que je gomme l'interface matlab en mex, mais ca va le faire. A très prochainement

  10. #10
    Membre confirmé
    Inscrit en
    Février 2013
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 94
    Par défaut
    rebonjour,

    Voici un exemple presque minimal qui reproduit bien le problème (fichier 'min_example.cpp' en PJ).
    J'ai du ajouter quelques bouts de code pour remplir la matrice d'adjacence, et initialiser les structures que j'utilise dans le code, mais ca fonctionne en local.

    Vous constaterez que chaque itération est plus lente que la précédente (je n'en saisis pas la raison).

    merci!
    Fichiers attachés Fichiers attachés

  11. #11
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct mypq :public priority_queue<int,vector<int>,cmp> {
        void clear(){
            size_t prevsize = c.size();
            c.clear();
            c.reserve( prevsize * 2u + 1u );
        }
    };
    Je ne suis pas convaincu par ce code.
    Le clear ne fait généralement aucun traitement sur la mémoire réservée, il se contente d'appeler les destructeurs des éléments utilisés, éventuellement de remettre la mémoire à 0, et de mettre à jour la taille effective.
    En ajoutant un reserve, tu forces une allocation.

    Le code présenté est loin de suivre certaines bonnes pratiques.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
            //Fill the structure:
            for(i=0; i < N; i++)
            {
                //rempli les liens (ici pour le noeud 'a' met un lien vers 'b',
                //autrement dit pousse les noeuds connect�s dans 'a'):
                for(j=0; j < N; j++) { //nrows * 2 ?
                    if(A[i + j*N] == 1) {
                        graph[i].push_back(j);
                        weight[i].push_back(1);  //ajoute le poids. (idem ici)
                    }
                }
            }
    Je n'ôse imaginer le nombre de réallocation qui surviennent sur ces seules boucles..
    Idem dans djikstra avec pq.

    Au passage, l'utilisation de variables globales n'a rien d'obligatoire ici et devrait donc être proscrit.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    J'ai effectué quelques modifications dans ton code, et désormais tout s’exécute en temps constant d'une itération à l'autre. Mais je ne garanti pas que ça fasse totalement ce que tu voulais que ça fasse...

    En résumé :
    - J'ai ajouté une mesure du temps, pour mieux suivre
    - J'ai enlevé tes bricolages avec la priority queue.
    - Te ne remettais jamais à 0 les éléments de A, ton graphe était donc de plus en plus connecté
    - Tes variables globales ne faisaient qu'augmenter en taille à chaque itération. Je les ai remises à 0 (il faudrait bien entendu qu'elles ne soient plus globales)

    En outre :
    - Ton code mélange du C et du C++, ce qui le rend moins simple à lire. Pourquoi A n'est pas un simple vector par exemple ? Idem pour rand_idx
    - Il faut vraiment virer ces globales
    - Remplacer random_shuffle par std::shuffle
    - L'ai-je déjà mentionné ?... Virer ces variables globales !



    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
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    // PriorityQueueBench.cpp*: définit le point d'entrée pour l'application console.
    //
     
    #include "math.h"
    #include <stdlib.h>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>    // std::random_shuffle
    #include <ctime>        // std::time
    #include <cstdlib>      // std::rand, std::srand
    #include <vector>
    #include <climits>
    #include <queue>
    #include <chrono>
     
    using namespace std;
     
    vector < vector <int> > graph;
    vector < vector <int> > weight;
    vector < int> cost;
    int N;
     
    struct cmp {
      bool operator()(const int &lhs, const int &rhs) const {
        return cost[lhs] > cost[rhs];
      }
    };
     
    int min(const int a, const int b) {
      if (a<b)
        return a;
      return b;
    }
     
     
    struct mypq :public priority_queue<int, vector<int>, cmp> {
      void clear() {
        //size_t prevsize = c.size();
        c.clear();
        //c.reserve(prevsize * 2u + 1u);
      }
    };
     
    mypq pq;
     
    int dijkstra(const int from, const int to) {
      vector <bool> visited(N, false);
      visited[from] = true;
      cost[from] = 0;
      pq.push(from);
      while (!pq.empty() && !visited[to]) {
        int current = pq.top();
        pq.pop();
        visited[current] = true;
        for (int i = 0; i<graph[current].size(); i++) {
          if (!visited[graph[current][i]]) {
            cost[graph[current][i]] = min(cost[graph[current][i]], cost[current] + weight[current][i]);
            pq.push(graph[current][i]);
          }
        }
      }
      return cost[to];
    }
     
    void resetGlobals() {
      graph.clear();
      weight.clear();
      //Initialize structure:
      for (int i = 0; i < N; i++) {
        graph.push_back(vector <int>());
        weight.push_back(vector <int>());
        cost.push_back(INT_MAX);
      }
     
    }
    /****************************************************************************/
    /* Core Program                                                             */
    /****************************************************************************/
    int main(void) {
      /***********************************
      *DECLARATIONS AND INITS
      ***********************************/
      int i, j, n_sims;
      int *A, *rand_idx;
     
      N = 25; // size of network
      n_sims = 200;
     
      /* initialize random seed: */
      std::srand(unsigned(std::time(0)));
     
      //assign rand_idx and shuffle the nodes values:
      rand_idx = (int*)malloc(N * sizeof(int));
      for (i = 0; i < N; i++)
        rand_idx[i] = i; //fill vector.
      std::random_shuffle(&rand_idx[0], &rand_idx[N]); //then shuffle
     
                                                       //Adjacency matrix (linear index):
      A = (int*)calloc(N * N, sizeof(int));
     
     
      for (int k = 0; k < n_sims; k++) {
        resetGlobals();
        std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
     
        //Fill adjacency matrix 'A' with random values:
        for (i = 0; i < N; i++) {
          //randomly fill the adjacency matrix:
          for (j = 0; j < N; j++) {
            A[i + j * N] = (rand() % 4 == 1) ? 1 : 0;//one chance over 5 (possibly no connected node is ok)
          }
        }
     
        //Fill the structure:
        for (i = 0; i < N; i++) {
          //rempli les liens (ici pour le noeud 'a' met un lien vers 'b',
          //autrement dit pousse les noeuds connect�s dans 'a'):
          for (j = 0; j < N; j++) { //nrows * 2 ?
            if (A[i + j * N] == 1) {
              graph[i].push_back(j);
              weight[i].push_back(1);  //ajoute le poids. (idem ici)
            }
          }
        }
     
        //Then perform the search for inflow and outflow nodes (find requested distance):
        for (i = 0; i < N; i++) {
          //for earch values of 'R', compute the distance with other nodes in 'R':
          //search for distance 'distance' in other nodes using dijkstra's algorithm:
          for (j = 0; j < N; j++) {
            if (rand_idx[i] < j && rand_idx[i] != N - 1) { //only read the upper triangular part and omit the last line.
              const int cur_dis = dijkstra(rand_idx[i], j);
              //je me sers de cur_dis dans le code non minimal ici:
              //s'il rencontre un certain critère de distance, on s'arrête
              //et on est content.
            }
          }
        }
     
        //we browsed 'A' without finding the requested distance, thus assign '-1' to outputs
        //(utilise l'interface MEX pour matlab normallement (non utilisée dans cet exemple minimal)
        /*plhs[0] = mxCreateDoubleScalar(-1.0); //in
        plhs[1] = mxCreateDoubleScalar(-1.0); //out
        plhs[2] = mxCreateDoubleScalar(-1.0); //fdistance*/
        pq.clear();
        std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
     
        std::cout << "Iteration "<< k << "; duration = " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << std::endl;
      }
     
      free(rand_idx);
      free(A);
      return 1;
    }
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

Discussions similaires

  1. Détection de fuites mémoire avec Valgrind
    Par dj.motte dans le forum GTK+ avec C & C++
    Réponses: 25
    Dernier message: 22/11/2008, 08h49
  2. Fuite mémoire avec code externe
    Par samW7 dans le forum C++
    Réponses: 8
    Dernier message: 01/02/2008, 02h33
  3. [AJAX] Appolo 13 - Fuite mémoire avec XHR
    Par mecatroid dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 24/09/2007, 14h52
  4. Fuites mémoires avec Vector
    Par ..alex.. dans le forum SL & STL
    Réponses: 15
    Dernier message: 10/08/2006, 11h35
  5. Fuite mémoire avec valgrind
    Par franchouze dans le forum C++
    Réponses: 3
    Dernier message: 05/06/2006, 16h47

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