Fix memleaks in pooptmodule.cut_text (ref #1914)
- we need to decrement the refcount after giving the tuple to the retlist in order to transfer ownership The example script below will quickly take gigabytes of ram with the old module, while the new will not take noticeably more memory. The leak is not very visible on launch, because we “only” leaked each tuple returned, and (int, int) is not heavy. However, after weeks of use and many messages, the memory still isn’t freed and it shows. import poopt import gc a = 'coucouco ' * 1000 for i in range(100000): if not (i % 10000): print(i) poopt.cut_text(a, 50)
This commit is contained in:
parent
5999b71c41
commit
3fb3d8db3d
1 changed files with 26 additions and 4 deletions
|
@ -63,6 +63,8 @@ static PyObject* poopt_cut_text(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
/* The list of tuples that we return */
|
/* The list of tuples that we return */
|
||||||
PyObject* retlist = PyList_New(0);
|
PyObject* retlist = PyList_New(0);
|
||||||
|
/* The temporary name for the tuples */
|
||||||
|
PyObject* tmp;
|
||||||
|
|
||||||
/* Get the python arguments */
|
/* Get the python arguments */
|
||||||
const size_t width;
|
const size_t width;
|
||||||
|
@ -146,8 +148,13 @@ static PyObject* poopt_cut_text(PyObject* self, PyObject* args)
|
||||||
if (wc == (wchar_t)'\n')
|
if (wc == (wchar_t)'\n')
|
||||||
{
|
{
|
||||||
spos++;
|
spos++;
|
||||||
if (PyList_Append(retlist, Py_BuildValue("II", start_pos, spos)) == -1)
|
tmp = Py_BuildValue("II", start_pos, spos);
|
||||||
|
if (PyList_Append(retlist, tmp) == -1)
|
||||||
|
{
|
||||||
|
Py_XDECREF(tmp);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tmp);
|
||||||
/* And then initiate a new line */
|
/* And then initiate a new line */
|
||||||
start_pos = spos;
|
start_pos = spos;
|
||||||
last_space = -1;
|
last_space = -1;
|
||||||
|
@ -164,8 +171,13 @@ static PyObject* poopt_cut_text(PyObject* self, PyObject* args)
|
||||||
{ /* If possible, cut on a space */
|
{ /* If possible, cut on a space */
|
||||||
if (last_space != -1)
|
if (last_space != -1)
|
||||||
{
|
{
|
||||||
if (PyList_Append(retlist, Py_BuildValue("II", start_pos, last_space)) == -1)
|
tmp = Py_BuildValue("II", start_pos, last_space);
|
||||||
|
if (PyList_Append(retlist, tmp) == -1)
|
||||||
|
{
|
||||||
|
Py_XDECREF(tmp);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tmp);
|
||||||
start_pos = last_space + 1;
|
start_pos = last_space + 1;
|
||||||
last_space = -1;
|
last_space = -1;
|
||||||
columns -= (cols_until_space + 1);
|
columns -= (cols_until_space + 1);
|
||||||
|
@ -173,8 +185,13 @@ static PyObject* poopt_cut_text(PyObject* self, PyObject* args)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Otherwise, cut in the middle of a word */
|
/* Otherwise, cut in the middle of a word */
|
||||||
if (PyList_Append(retlist, Py_BuildValue("II", start_pos, spos)) == -1)
|
tmp = Py_BuildValue("II", start_pos, spos);
|
||||||
|
if (PyList_Append(retlist, tmp) == -1)
|
||||||
|
{
|
||||||
|
Py_XDECREF(tmp);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tmp);
|
||||||
start_pos = spos;
|
start_pos = spos;
|
||||||
columns = 0;
|
columns = 0;
|
||||||
}
|
}
|
||||||
|
@ -194,8 +211,13 @@ static PyObject* poopt_cut_text(PyObject* self, PyObject* args)
|
||||||
spos++;
|
spos++;
|
||||||
}
|
}
|
||||||
/* We are at the end of the string, append the last line, not finished */
|
/* We are at the end of the string, append the last line, not finished */
|
||||||
if (PyList_Append(retlist, Py_BuildValue("II", start_pos, spos)) == -1)
|
tmp = Py_BuildValue("II", start_pos, spos);
|
||||||
|
if (PyList_Append(retlist, tmp) == -1)
|
||||||
|
{
|
||||||
|
Py_XDECREF(tmp);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tmp);
|
||||||
return retlist;
|
return retlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue