【问题标题】:Reference counting for c++ functionc++函数的引用计数
【发布时间】:2014-06-12 13:05:50
【问题描述】:

当我运行这段代码时,我的内存有问题,所以我想我应该使用PY_DECREF() 来释放内存,但我不知道把它放在哪里?有什么帮助吗?我试图将它放在代码的末尾,就在返回pArgs 之前,但它似乎不起作用。

此代码准备发送到 python 函数的参数,以便用计数列表填充pArgs。每个列表都是 python 函数的一个参数。

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;
}

【问题讨论】:

  • 在退出函数之前你肯定错过了delete[] tuplelist
  • 我知道我添加了删除元组列表,但似乎并没有解决问题。我肯定需要添加一些 Py_DECREF

标签: python c++ cpython reference-counting


【解决方案1】:

我建议您查看您使用的每种 Python 方法的文档,以了解您何时拥有一个 Python 对象或何时借用一个 Python 对象。

  1. pArgs 是用PyTuple_New() 创建的。如果您没有返回pArgs(例如,由于错误而返回NULL),您必须通过Py_DECREF(pArgs) 释放您的所有权。

  2. pValue 是一个临时变量,用于保存一个 python 对象,所以我们稍后会在使用它时回到它。

  3. tuplelist 是一个 Python 对象数组。在您退出该功能之前,您必须delete[] tuplelist(正如user4815162342 所指出的那样)。 但在你删除它之前,你必须释放它所持有的任何 python 对象,方法是在它上面迭代 Py_XDECREF(item)Py_XDECREF() 可以安全地用于 NULL 指针)。(参见第 7 点) )

  4. tuplelist[j] 中的项目是使用 PyList_New() 创建的。您拥有 tuplelist 中的项目,但要发布参考,请参阅第 7 条。

  5. pValue 是用PyString_FromString() 创建的。你拥有这个字符串。然后你打电话给PyList_SetItem(tuplelist\[j\], ..., pValue),这会从你那里窃取pValue的所有权,这意味着不要Py_DECREF(pValue)

  6. pValue 是用PyInt_FromLong() 创建的。您拥有此整数,但调用 PyList_SetItem(tuplelist[j], ..., pValue) 时,您的所有权被盗,因此您不得使用 Py_DECREF(pValue)

  7. 最后你 PyTuple_SetItem(pArgs, j, tuplelist[j]) 窃取了 tuplelist[j] 的所有权,这使得这很棘手。如果您因错误而提前失败(当您返回 NULL 时),那么您必须只使用 Py_DECREF(tuplelist[j]),但不要释放 tuplelist 中的对象,因为其中的任何先前引用都是借用的,因为它们被盗了。

【讨论】:

  • 谢谢。当我添加这个: for(h=0;h
  • @user3516044 如果您还没有PyTuple_SetItem() for tuplelist[j] 并且遇到错误,那么您才只想Py_DECREF(tuplelist[j])。如果一切都成功了,那么不要在 tuplelist 中删除任何项目,只有 delete[] tuplelist
  • 你是个有耐心的人。 :) 但是,如果没有遇到错误,唯一缺少的部分是delete[] tuplelist。 (事实上​​,tuplelist 根本没有必要,OP 可以在创建对象时将它们直接保存到pArgs。)一旦添加,内存问题很可能是程序其他部分的错误。
  • 嗨,你说的我都做了,但我仍然有内存泄漏问题,我确定问题出在这个函数上。
  • @user3516044 您可以将更新后的代码添加到您的帖子中吗?
猜你喜欢
  • 2012-04-11
  • 1970-01-01
  • 2014-12-21
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2016-08-18
相关资源
最近更新 更多