Core dump revisited
Nick Craig-Wood
nick at craig-wood.com
Tue Dec 19 14:30:05 EST 2006
Sheldon <shejo284 at gmail.com> wrote:
> Man. You are good. This is most insight I have had from anyone.
:-)
> I did initialize the arrays with PyObjects and today, after hours of
> debugging and now with your insight, I think the problem lies here:
Good!
You need to release some python references otherwise you'll have a
memory leak and copy some strings you don't own
It is worth reading the definitions for those functions in the Python
API docs
http://docs.python.org/api/api.html
In particular read about reference counts.
With the Python C API you have to know at all time (by reading the
doc) whether you own the reference or not, and whether you own the
memory or not.
> /* here a python list of strings is read into a C string array */
> static int readPythonObject(void) {
>
> int i;
> PyObject *msgop;
> PyObject *ppsop;
> PyObject *tileop;
> PyObject *sceneop;
>
> for (i = 0; i < work.sumscenes; i++) {
> msgop = PyList_GetItem(work.msgobj, i);
> work.msg_scenes[i] = PyString_AsString(msgop);
work.msg_scenes[i] = strdup(PyString_AsString(msgop));
Py_DECREF(msgop);
> ppsop = PyList_GetItem(work.ppsobj, i);
> work.pps_scenes[i] = PyString_AsString(ppsop);
work.pps_scenes[i] = strdup(PyString_AsString(ppsop));
Py_DECREF(ppsop);
> }
> for (i = 0; i < NumberOfTiles; i++) {
> tileop = PyList_GetItem(work.tileobj, i);
> work.tiles[i] = PyString_AsString(tileop);
work.tiles[i] = strdup(PyString_AsString(tileop));
Py_DECREF(tileop);
> sceneop = PyList_GetItem(work.nscenesobj, i);
> work.nscenes[i] = PyInt_AsLong(sceneop);
Py_DECREF(sceneop);
> }
> return 1;
> } /*end readPythonObject*/
You free() the strings later which is fine.
The above ignores errors which PyList_GetItem may return and strdup()
returning 0, but it should get you out of trouble hopefully.
...
I've written lots of quite similar code, here is a snippet. Note the
comments about who owns the reference, and the error checking. Also
note xstrdup() which is a strdup() which blows up if no memory is
available.
[snip]
PyObject *item = PySequence_GetItem(value, i); /* real ref */
if (item == 0)
{
fprintf(stderr, "Failed to read '%s[%d]' attribute\n", name, i);
goto err;
}
item_cstr = PyString_AsString(item); /* borrowed */
if (item_cstr == 0)
{
fprintf(stderr, "Failed to read '%s[%d]' as string\n", name, i);
goto err;
}
label[i] = xstrdup(item_cstr);
Py_DECREF(item);
item = 0;
[snip]
err:;
PyErr_Print();
out:;
if (value)
Py_DECREF(value);
if (item)
Py_DECREF(item);
return rc;
--
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick
More information about the Python-list
mailing list