tiny extension crashes

Greg Jorgensen gregj at pobox.com
Fri Mar 16 01:42:46 EST 2001


"John J. Lee" <phrxy at csv.warwick.ac.uk> wrote in message
news:Pine.SOL.4.30.0103152349300.26347-100000 at mimosa.csv.warwick.ac.uk...

> What I still don't get, though, is why it was crashing even when only the
> hcf()  function was being imported and called by my (pure) Python code.
> Surely if it doesn't get called, the uninitialised pointer can't scribble
> over anything?

I don't see anything else as obvious as that dangling pointer. Can you give
any more debugging info? I would simplify the extensions bit by bit until
the code didn't crash, and then figure out what I had removed that was
causing the crash.

I haven't used the Numeric module's C API, but I did glance through the
docs. In both your array_max and hcf functions you pull long integers out of
the array with the expression *(long *)(array->data + i*array->strides[0]).
But the data elements aren't necessarily C long integers; your hcf function
will accept an array of short or long ints, and array_max doesn't check the
type at all. By casting the array pointer to long* and then fetching the
value pointed to, you are always fetching sizeof(long) bytes rather than the
size of the actual array elements. This may cause a crash if the OS is
watching your memory references, because at the end of the array you will be
fetching memory that isn't allocated to the array.

You can either test for the type like this:

    long elem;
    char *p;
    ...
    /* extract array[i] into elem, converting it to a long integer */
    p = array->data + i*array->strides[0];
    switch (array->descr->type_num ) {
        case PyArray_SHORT:
            elem = *(short *)p;
        case PyArray_INT:
            elem = *(int *)p;
        case PyArray_LONG:
            elem = *(long *)p;
        default:
            /* error */
    }
    ...

The Numeric module and C API may have better/easier ways to handle this.

> In fact I'll probably scrap all of these functions eventually -- they're
> only there because they were the simplest functions I had lying around,
> and I knew I'd certainly get tangled up in C if I picked something more
> complicated for my first extension.)

Here's a Python GCD implementation. It would of course be faster in C. The
algorithm is a little better than the one you are using. ;-)

def gcd(a,b)
    " return greatest common denominator of a and b"
    g = b
    while a > 0:
        g = a
        a = b % a
        y = g
    return g

def gcdlist(a)
    " return gcd of all numbers in list"
    g = a[0]
    for v in a:
        g = gcd(g,v)
    return g

Argument checking and error handling omitted for brevity.

--
Greg Jorgensen
PDXperts
Portland, Oregon, USA
gregj at pobox.com





More information about the Python-list mailing list