J
John Hunter
I have a function that is leaking memory; I have removed all the
extraneous code just to focus on the leak. This function contains the
leak
static PyObject *
pokereval_debug_leak(PyObject *self, PyObject *args)
{
int i, N;
char* cardstr;
PyObject* player0;
PyObject* player1;
if (!PyArg_ParseTuple(args, "OO", &player0, &player1)) {
PyErr_SetString(PyExc_ValueError,
"Usage compare_two_hands(player0, player1)");
return NULL;
}
N = PySequence_Length(player0);
// init the pokereval vars from the python args
for (i=0; i<N; ++i) {
cardstr = PyString_AsString(PySequence_GetItem(player0, i)); //no leak
cardstr = PyString_AsString(PySequence_GetItem(player1, i)); //leak
}
return Py_BuildValue("(iiif)", 0,0,0,0.0);
}
The python code that calls this function is
for s in enumerate_down(down, common):
player1 = s.split()
wins, losses, ties, ev = debug_leak( player0, player1 )
Ie, player0 is the same in every call and player 1 is created on each
iteration through the loop. player0 and player1 are equal length
tuples of strings.
Am I doing something wrong vis-a-vis memory handling? Only the
player1 line in the C code labeled "leak" produces a detectable leak
(determined by selective commenting out). My understanding is that
PySequence_GetItem returns a borrowed ref so I don't need to do any
memory management. What about PyString_AsString. It's interesting to
me that the leak is dependent on how the object was created in the
python code.
If I change the loop to
opponentDown = ('AH', 'QD')
for s in enumerate_down(down, common):
wins, losses, ties, ev = debug_leak( tuple(down), tuple(opponentDown) )
I have no detectable leak. If the code is erroneous (most likely!),
please let me know where. If not, I'll write up a complete, free
standing example that replicates it.
Thanks
extraneous code just to focus on the leak. This function contains the
leak
static PyObject *
pokereval_debug_leak(PyObject *self, PyObject *args)
{
int i, N;
char* cardstr;
PyObject* player0;
PyObject* player1;
if (!PyArg_ParseTuple(args, "OO", &player0, &player1)) {
PyErr_SetString(PyExc_ValueError,
"Usage compare_two_hands(player0, player1)");
return NULL;
}
N = PySequence_Length(player0);
// init the pokereval vars from the python args
for (i=0; i<N; ++i) {
cardstr = PyString_AsString(PySequence_GetItem(player0, i)); //no leak
cardstr = PyString_AsString(PySequence_GetItem(player1, i)); //leak
}
return Py_BuildValue("(iiif)", 0,0,0,0.0);
}
The python code that calls this function is
for s in enumerate_down(down, common):
player1 = s.split()
wins, losses, ties, ev = debug_leak( player0, player1 )
Ie, player0 is the same in every call and player 1 is created on each
iteration through the loop. player0 and player1 are equal length
tuples of strings.
Am I doing something wrong vis-a-vis memory handling? Only the
player1 line in the C code labeled "leak" produces a detectable leak
(determined by selective commenting out). My understanding is that
PySequence_GetItem returns a borrowed ref so I don't need to do any
memory management. What about PyString_AsString. It's interesting to
me that the leak is dependent on how the object was created in the
python code.
If I change the loop to
opponentDown = ('AH', 'QD')
for s in enumerate_down(down, common):
wins, losses, ties, ev = debug_leak( tuple(down), tuple(opponentDown) )
I have no detectable leak. If the code is erroneous (most likely!),
please let me know where. If not, I'll write up a complete, free
standing example that replicates it.
Thanks