c-extension crashes unexpected

John Machin sjmachin at lexicon.net
Fri Apr 22 16:35:53 EDT 2005


On 22 Apr 2005 07:37:11 -0700, garz at tmft.net (Markus Wintermann)
wrote:

>hello,
>
>i try to write an extension which calls an api.
>however,
>i haven´t written very much till now, 
>but i`ve already managed to make a mistake.
>
>because when i try to call my function,
>python 2.4 dies with an errorwindow.
>
>i believe that has something todo with reference counts and memory
>allocation but i can´t find my mistake.
>
>here´s the code:
>
>/* Wrapper-Funktion für apiJob() */
>static PyObject* wrap_apiJob(PyObject* self, PyObject* args) {
>
>	PyObject *resultlist;
>	unsigned short i,j,setcount,resultcount;
>
>	for (i=0;i<setcount+1;i++) {
>		PyList_SetItem(resultlist, i, Py_BuildValue("i",i));

Thomas has already shown you where your particular bug is. However you
have a general problem. Look at the documentation for PyList_SetItem
and Py_BuildValue:
"""
int PyList_SetItem( PyObject *list, int index, PyObject *item) 

Sets the item at index index in list to item. Returns 0 on success or
-1 on failure. Note: This function ``steals'' a reference to item and
discards a reference to an item already in the list at the affected
position. 

PyObject* Py_BuildValue( char *format, ...) 

Return value: New reference. 
Create a new value based on a format string similar to those accepted
by the PyArg_Parse*() family of functions and a sequence of values.
Returns the value or NULL in the case of an error; an exception will
be raised if NULL is returned.  <snip>
"""

You are not testing for errors after PyBlahBlah() function calls.

The last line of your code that I quoted above should be replaced by
something like this:

    val = Py_BuildValue("i",i);
    if (val == NULL) BOGOFF(1);
    if PyList_SetItem(resultlist, i, val) BOGOFF(2);

where BOGOFF(n) is a #define that prints something like "Problem n in
<myfunc>" if you are in debug mode, and then does a "goto cleanup"
where you release resources and return NULL;    

This testing (and the following purist-horrifying "goto" to get to
your clean-up block) is an unfortunate but necessary part of using the
Python C API. 

Some suggestions:

1. Try Pyrex. You get to write in a higher-level language and it does
all the boring ugly error-prone stuff for you -- this includes
reference counting as well! Look at the C code that Pyrex generates,
to see what Pyrex is saving you from.
2. If you still insist on DIY, look at some of the Python source code
in the Modules and Objects directories to see how it is done.
3. Examine carefully the book or whatever you have been learning from.
If it doesn't cover topics like always checking for errors, throw it
in the garbage bin (and tell the world via this newsgroup). If it does
cover such topics but you've been ignoring it, well then, it's up to
you what you do next :-)

HTH,
John



More information about the Python-list mailing list