[Cython] Bug, or changed array assignment in 0.17beta1?

Stefan Behnel stefan_ml at behnel.de
Wed Jul 25 08:29:39 CEST 2012


Stefan Behnel, 25.07.2012 07:40:
> Mike Zaletel, 25.07.2012 00:40:
>> --------bug.pyx----------
>>
>> def foo():
>>        cdef int i
>>        cdef int* p1 = [4, 4]
>>        cdef int* p2 = [5, 5]
>>
>>        print "p1:",
>>        for i in range(2):
>>                print p1[i],
>>        print "\np2:",
>>        for i in range(2):
>>                print p2[i],
>>
>> -----------------------------
>>
>> which in Cython 0.17beta1 gives me
>>
>> >>> import bug
>> >>> bug.foo()
>> p1: 5 5
>> p2: 5 5
>>
>>
>> while in Cython 0.16 I get
>>
>> >>> import bug
>> >>> bug.foo()
>> p1: 4 4
>> p2: 5 5
> 
> The problem is that the same (temporary) local array variable is used in
> both cases to build the array, and then only a pointer is assigned, i.e. p1
> and p2 then point to the same array, which gets overwritten with the new
> values in the second assignment.

Looking into this some more, the problem arises from the pointer
assignment, because the left side is a pointer variable whereas the right
side is a temp value. Temps aren't really made for an enduring life. Here,
the array temp variable is being freed after the assignment and then
reused. We could fix it by not freeing the temp, or at least by not reusing
it, but the problem is really in the syntax. The LHS should be an array,
not a pointer.

It broke (and I broke it) when I fixed pointer type comparisons and made
pointer and array types properly hashable. I think it was already subtly
broken before in Py2 and just didn't show because it's sufficiently
unlikely that two equal array types that use the default hash by object
id() end up in the same dict bucket. Only then would the __eq__()
comparison strike to reuse the same temp for both types.

Stefan



More information about the cython-devel mailing list