-3

When i run this code, i have a problem with the memory so i think i should use PY_DECREF() in order to free the memory, but i don't know where to put it ? Any help ? I've tried to put it at the end of the code, just before returning pArgs but it doesn't seem to work.

This code prepares the argument that are sent to a python function so it fills pArgs with count lists. Each list is an argument of the python function.

PyObject * Ecrire::getArgumentsbis(PythonRetour * pr){

    int j = 0 ;
    PyObject * pArgs = NULL;
    int count=pr->numberargs;

    pArgs = PyTuple_New(count);

    PyObject * pValue;
    PyObject ** tuplelist = new PyObject*[count];

    for(j = 0; j < pr->numberargs; j++){

        std::string argument = pr->nom_args[j];
        int buffer = pr->buffer[j]+1;
        tuplelist[j] = PyList_New(buffer);

        if(ends_with_string(argument,"%#C#%"))
            argument = argument.substr(0, argument.size()-5);

        if(valeurs.size() >= buffer){

            int l;

            for(l = 0; l < buffer; l++){

                map<std::string,pvalues>::const_iterator it = valeurs[valeurs.size() - 1 - l].find(argument);

                if (it != valeurs[valeurs.size() - 1 - l].end()){

                    if(ends_with_string(pr->nom_args[j], "%#C#%")){

                        if((*it).second.type == "enumere"){

                            std::string valueread = (*it).second.val;
                            unsigned long long numberread;
                            istringstream(valueread) >> numberread;
                            std::map<std::string,inf_analyse>::const_iterator iter=mat->liste_analyse.find(argument);

                            if (iter != mat->liste_analyse.end()){

                                bool check = false;
                                std::string valuecorr = "";
                                int k = 0;

                                for(k=0;k<(*iter).second.nombre_valeurs;k++){

                                    if((*iter).second.valeurs[k] == numberread) {
                                        check = true;
                                        valuecorr = (*iter).second.correspondances[k];
                                        break;
                                    }
                                }

                                if(check) {
                                    pValue = PyString_FromString(valuecorr.c_str());
                                    PyList_SetItem(tuplelist[j], buffer - l - 1, pValue);
                                }
                                else
                                  return NULL;

                            }
                        }
                    }

                    else {

                        if((*it).second.type == "enumere"){
                            std::string valueread = (*it).second.val;
                            unsigned long long numberread;
                            istringstream(valueread) >> numberread;
                            pValue = PyInt_FromLong(numberread);

                            PyList_SetItem(tuplelist[j], buffer - l - 1, pValue);
                        }

                        else if((*it).second.type == "autre") {
                            std::string valueread = (*it).second.val;
                            double numberread;
                            istringstream(valueread) >> numberread;
                            pValue = Py_BuildValue("d", numberread);

                            PyList_SetItem(tuplelist[j], buffer - l - 1, pValue);
                        }

                        else if((*it).second.type == "chaine"){
                            std::string valueread = (*it).second.val;
                            pValue = PyString_FromString(valueread.c_str());

                            PyList_SetItem(tuplelist[j], buffer - l - 1, pValue);
                        }

                    }

                }

                else
                  return NULL;
            }

        }

        else
          return NULL;

        PyTuple_SetItem(pArgs,j, tuplelist[j]);
    }

    return pArgs;
}
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144

1 Answers1

1

I would recommend looking at the documentation for each Python method you're using to understand when you own a python object or when you're borrowing one.

  1. pArgs is created with PyTuple_New(). If you are not returning pArgs (e.g., you return NULL because of an error), you must release your ownership with Py_DECREF(pArgs).

  2. pValue is a temporary variable used to hold a python object so we'll come back to this later when it's used.

  3. tuplelist is an array of python objects. Before you exit the function you must delete[] tuplelist (as pointed out by user4815162342). But before you can delete it, you must release any python objects it holds by iterating over it an Py_XDECREF(item) (Py_XDECREF() is safe to use on NULL pointers). (see bullet #7)

  4. An item in tuplelist[j] is created with PyList_New(). You own the item in tuplelist but to release the reference see bullet #7.

  5. pValue is created with PyString_FromString(). You own this string. Then you call PyList_SetItem(tuplelist\[j\], ..., pValue) which steals the ownership of pValue from you which means DO NOT Py_DECREF(pValue).

  6. pValue is created with PyInt_FromLong(). You own this integer, but by calling PyList_SetItem(tuplelist[j], ..., pValue) your ownership of it is stolen so you MUST NOT Py_DECREF(pValue).

  7. At the end you PyTuple_SetItem(pArgs, j, tuplelist[j]) which steals the ownership from tuplelist[j] which makes this tricky. If you fail early with an error (when you return NULL), you must then only Py_DECREF(tuplelist[j]) but DO NOT FREE the objects within tuplelist because any prior references in it are borrowed because they were stolen.

Community
  • 1
  • 1
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
  • thank you. when i add this : for(h=0;h – user3516044 Jun 12 '14 at 14:53
  • @user3516044 If you have not yet `PyTuple_SetItem()` for `tuplelist[j]` and you encounter an error, only then do you want to only `Py_DECREF(tuplelist[j])`. If everything succeeds, then DO NOT decref any items in `tuplelist`, only `delete[] tuplelist`. – Uyghur Lives Matter Jun 12 '14 at 14:57
  • You are a patient man. :) But, in case no error is encountered, the only part missing is `delete[] tuplelist`. (In fact, `tuplelist` is not necessary at all, the OP could save the objects directly into `pArgs` as they get created.) Once that is added, memory problems are likely the fault of some other part of the program. – user4815162342 Jun 12 '14 at 16:58
  • Hi, I did everything you said but i still have a memory leak problem and I'm sure the problem comes from this function. – user3516044 Jun 13 '14 at 07:58
  • @user3516044 Can you add your updated code to your post? – Uyghur Lives Matter Jun 13 '14 at 14:20
  • Hi i resolved the problem. Thank you every one for your help ! – user3516044 Jun 13 '14 at 14:38