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

Interfaçage autre langage Python Discussion :

fuite memoire PyList_setItem dans boucle


Sujet :

Interfaçage autre langage Python

  1. #1
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut fuite memoire PyList_setItem dans boucle
    Bonjour a tous
    me revoila avec un soucis de fuite memoire, mon code est le suivant :


    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    PyObject *list = PyList_New(taille_liste);
     
    for (i=0;i<taille_liste;i++)
    {
     
    /*calcul dune valeur que je vais stocker dans ma liste*/
     
    PyList_SetItem(list , i, PyInt_fromLong(valeur_calculee));
     
    }
     
    return list;

    Et lorsque je regarde l'evolution de la memoire physique au fur et a mesure que i progresse dans la boucle, elle grimpe elle grimpe elle grimpe.
    La fuite ne peut venir que de PyList_setItem

    est-ce que vous sauriez comment l'eviter ?

  2. #2
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    jai localise plus precisement la fuite memoire sans savoir comment la corriger

    en fait ma valeur calculee est un entier mais dont la valeur est obtenue ainsi :

    valeur_calculee = *(array + i)

    avec array etant une chaine de caractere , en fait cetait une array sous python mais ad je lai importee vers le C avec PyArg_ParseTuple, lindication "s#" l'a transformee en string et je vais juste chercher la valeur au bon endroit.

    y a til un moyen de lui dire ce que je te donne est un entier, et non une adresse.
    parce que quand je remplace dans PyList_setItem "valeur_calculee" par 3, je nai plus de fuite memoire..

    la fuite vient donc du fait que je remplit ma liste avec des adresses ...

    en esperant que cette precision vous aidera

    merci enormement davance

  3. #3
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    le probleme ne vient finalenement pas le fait que je lui donne une adresse
    car qd je remplit ma liste avec des 3, la memoire ne bouge pas
    avec des 30 idem
    avec des 300 il y a une fuite memoire
    serait ce une histoire de short int, long int ?

    est il possible de dire a PyList_new que la taille quon lui donne est un nombre de long et non de int ?

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Tu devrais faire autrement car le module array est difficile à manipuler avec l'API C de Python.

    Moi je transformerais l'array python en list python :

    Mon module en C
    (ici je ne fais que vérifier que l'argument est une liste
    puis je renvoie cette même liste) :
    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
     
    #include <Python.h>
     
    static PyObject *
    run(PyObject *self, PyObject *list)
    {
      if(!PyList_Check(list))
      {
        PyErr_SetString(PyExc_TypeError, "arg must be list");
        return NULL;
      }
      /* important : on rajoute une reference pour cet objet python avant de le retourner ! */
      Py_INCREF(list);
      return list;
    }
     
    static PyMethodDef methods[] = {
        {"run", (PyCFunction)run, METH_O, "Return list"},
        {NULL, NULL}
    };
     
    PyMODINIT_FUNC
    inittest(void)
    {
        Py_InitModule("test", methods);
    }

    Et au niveau code python :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    import array
    import test
    arr = array.array('i', [0,1,2,3,4,5,6,7,8,9])
    print test.run(arr.tolist())
    Ici c'est très basique mais tu peux manipuler facilement ta liste python dans la fonction C "run" .

  5. #5
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    le probleme ne vient pas de la manipulation de larray qui se fait tres bien finalement dans mon programme.
    Il ne me reste plus qua comprendre pourquoi quand je fais PyList_SetItem avec des valeurs inferieures a 100 tout marche niquel sans fuite, et quand je remplis avec des valeurs >100, jai des fuites memoires a chaque iteration !!

    Il faudrait juste que jarrive a resoudre cette histoire.

    Pour linstant jai ete oblige de scinder mes entiers en deux parties (en separant les centaines des dizaines et jenvoie ca vers python sans fuite memoire, le soucis est kil fo reconstruire la liste sous python et ca ca prend bcpppp de temps)

    Si je pouvais remplir ma liste telle quel avec des valeurs >100 sans fuite memoire ce serait niquel...

  6. #6
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    Jen peux plus de ce soucis, cest dingue quand meme qu'au dela de 100 ca merdouille, justement precisement au dela de 100, 99 aucun probleme, 100 et + >> fuite memoire...

    je ne trouve personne sur le net qui ait rencontre ce probleme... jai cherche dans les bug de python mais il ny a rien concernant ce probleme...


    help...

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Tu as un bout de code un peu plus complet de ce que tu veux faire ?

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    J'ai fait un test de base avec PyList_SetItem et en insérant 60000 entier suffisamment grand et je n'ai aucune fuite mémoire :

    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
     
    static PyObject *
    run(PyObject *self)
    {
      PyObject *list;
      int i;
      unsigned int taille = 60000;
      long tab[taille];
      for(i=0; i<taille; i++)
      {
        tab[i] = (long)i*12345;
      }
      list = PyList_New(taille);
      for(i=0; i<taille; i++)
      {
        PyList_SetItem(list, i, PyInt_FromLong(tab[i]));
      }
      return list;
    }
     
    static PyMethodDef methods[] = {
        {"run", (PyCFunction)run, METH_NOARGS, "Return list"},
        {NULL, NULL}
    };
    Par contre j'ai vu quelque chose :
    When memory buffers are passed as parameters to supply data to build objects, as for the s and s# formats, the required data is copied. Buffers provided by the caller are never referenced by the objects created by Py_BuildValue. In other words, if your code invokes malloc and passes the allocated memory to Py_BuildValue, your code is responsible for calling free for that memory once Py_BuildValue returns.

    Dans http://docs.python.org/c-api/arg.htm...#Py_BuildValue

    Il me semble que tu utilises s# pour passer ton array .

  9. #9
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    oui j'utilise s# mais j'ai meme essaye de remplacer mon remplissage de liste par PyList_setItem(list, position[i], PyInt_FromLong(100))
    et j'ai une fuite memoire. A vrai dire je ne sais pas vraiment si cest une fuite memoire.

    Parce que si a linitialisation de mon code je remplis ma liste avec que des valeurs >100 et que je travaille ensuite dessus en y inserant les vrais valeurs la memoire ne bouge plus.

    Je crois que ca vient de la taille que prend un entier >100, pourtant je navais jamais rien vu de ce type auparavant, il y a les int et les long mais 100 fait encore et de loin partie des int...

    Mon code ressemble au tient a peu de choses pres... je vais essayer de lancer ton code pour voir

  10. #10
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    Jai essaye ton code, avec 60000 effectivement aucune fuite memoire, mais moi je travaille avec 12.000.000 dechantillons, du coup si japplique ton code avec ce nombre au lieu de 60000 jai une erreur de segmentation (pourquoi ?) jai donc tente en faisant plutot
    long* tab;
    tab=(long*)malloc(sizeof(long)*12000000);

    et la quand je remplis ma liste avec PyList_setItem, la memoire augmente follement...

    je crois quon ne peut rien faire a ce probleme, c juste que ce volume de donnees doit occuper de la memoire tout simplement, il ny a peut etre pas de fuites memoire derriere tout ca finalement...

    qu'en penses tu ?

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Ce code marche :

    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
     
    static PyObject *
    run(PyObject *self)
    {
      PyObject *list, *l;
      int i;
      unsigned int taille = 12000000;
      list = PyList_New(0);
      for(i=0; i<taille; i++)
      {
        l = PyInt_FromLong((long)tab[i]*12345);
        if(PyList_Append(list, l) == -1)
        {
          PyErr_Print();
          return NULL;
        }
      }
      return list;
    }

    Le problème de segfault se situe au niveau du tableau C : long tab[12000000]

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Il faut un malloc et un free sinon ta mémoire n'est jamais libérée :

    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
     
    #include <Python.h>
    #include <structmember.h>
     
    static PyObject *
    run(PyObject *self)
    {
      PyObject *list, *l;
      int i;
      unsigned int taille = 12000000;
      long *tab;
     
      list = PyList_New(0);
      tab = malloc(taille*sizeof(long));
      for(i=0; i<taille; i++)
      {
        l = PyInt_FromLong((long)tab[i]*12345);
        if(PyList_Append(list, l) == -1)
        {
          PyErr_Print();
          free(tab);
          return NULL;
        }
      }
      free(tab);
      return list;
    }
     
    static PyMethodDef methods[] = {
        {"run", (PyCFunction)run, METH_NOARGS, "Return list"},
        {NULL, NULL}
    };
     
     
    PyMODINIT_FUNC
    inittest(void)
    {
        Py_InitModule("test", methods);
    }

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    271
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 271
    Points : 329
    Points
    329
    Par défaut
    Un code un peu plus dans l'esprit Python C API (en utilisant les fonctions de l'api Python d'allocation/libération de la mémoire) :

    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
     
    static PyObject *
    run(PyObject *self)
    {
      PyObject *list, *l;
      int i;
      unsigned int taille = 12000000;
      long *tab = PyMem_New(long, taille);
      list = PyList_New(0);
      for(i=0; i<taille; i++)
      {
        l = PyInt_FromLong((long)tab[i]*12345);
        if(PyList_Append(list, l) == -1)
        {
          PyErr_Print();
          PyMem_Del(tab);
          return NULL;
        }
      }
      PyMem_Del(tab);
      return list;
    }

  14. #14
    Membre à l'essai
    Inscrit en
    Janvier 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 34
    Points : 12
    Points
    12
    Par défaut
    Merci bcp pour tes reponses je vais tester ca je te dirai le resultat.

    Merci encore

Discussions similaires

  1. Réponses: 17
    Dernier message: 01/12/2009, 09h24
  2. [JLabel] JLabel dans boucle for
    Par clairenes dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 06/01/2006, 00h47
  3. [VC++6] probleme fuite memoire CLIST ?
    Par athilla dans le forum MFC
    Réponses: 16
    Dernier message: 22/11/2005, 16h01
  4. Réponses: 12
    Dernier message: 10/11/2005, 09h05
  5. [ASE]probleme memoire: select dans une insert
    Par SegmentationFault dans le forum Sybase
    Réponses: 2
    Dernier message: 16/08/2005, 12h20

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