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