Core dump revisited

Sheldon shejo284 at gmail.com
Tue Dec 19 16:34:30 EST 2006


Nick Craig-Wood skrev:

> 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

Thanks Nick! Man, I really appreciate this. I did dereference before
but the program crashed and I did understand why so I kept on learning.
Now I have your snip. Much obliged.
I will be adding Numpy to my new PC in Jan and there I can pass arrays
instead of list. Still, I would like to save your email address i case
I have some mre questions later - if that ok with you?
I will make the changes and try to run the code.

/S




More information about the Python-list mailing list