1

OK, I'm getting a strange error after using Cython's C++ support as I think the manual advises (to use __cinit__ to allocate heap RAM and __dealloc__ to free it again.

I have a C++ class which calloc and mallocs some RAM in its constructor and frees it in the destructor. I will post this if necessary, but the error isn't coming from C++ land, and the new and delete calls work fine, so I'll just give you the cython for now:

cdef extern from "../clibs/adjacency.hpp":

  cdef cppclass Adjacency:
    int* _bv
    void** _meta
    unsigned int length
    Adjacency(int graph_order, int meta_on)
    int get(int i, int j)
    void set(int i, int j, int on, void* meta)
    void reset_to_zero()
    void edges_iter(void* global_meta, void (*callback)(void*, int, int, void*))

cdef class Graph:
  cdef Adjacency* adj

  def __init__(self, graph_order):
    print "__init__"

  def __cinit__(self, graph_order, *args, **kwargs):
    print "__cinit__"
    print "allocating, no meta."
    self.adj = new Adjacency(<int>graph_order, 0)

  def __dealloc__(self):
    print "__dealloc__"
    del self.adj

When I test this, I get the following:

In [1]: import graph

In [2]: g = graph.Graph(302)
__cinit__
allocating, no meta.
__init__

In [3]: ^D
Do you really want to exit ([y]/n)? 
__dealloc__
Python(7389,0x7fff70f9acc0) malloc: *** error for object 0x100defa08: incorrect
checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
Abort trap

I also sometimes get a segfault instead of an incorrect checksum.

I cracked open the C++ file that cython generated and added the following around the delete call:

/* "graph.pyx":75
 *   def __dealloc__(self):
 *     print "__dealloc__"
 *     del self.adj             # <<<<<<<<<<<<<<
 * 
 *   def __init__(self, graph_order):
 */
printf("about to delete adj:\n");
delete __pyx_v_self->adj;
printf("just deleted adj!\n");

and we can clearly see that the call I made to delete runs fine:

In [1]: import graph

In [2]: g = graph.Graph(302)
__cinit__
allocating, no meta.
__init__

In [3]: ^D
Do you really want to exit ([y]/n)? 
__dealloc__
about to delete adj:
just deleted adj!
Python(7389,0x7fff70f9acc0) malloc: *** error for object 0x100defa08: incorrect
checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
Abort trap

And that Python throws a tantrum after I'm done tidying up as I was told to in the Cython manual.

I also just tried setting self.adj = NULL in __dealloc__, in case Python was trying to see inside my object, but that didn't help.

Any ideas what I'm doing wrong?

4

1 に答える 1

0

I had made a mistake in my C++ code (which I didn't show).

I had a bunch of functions like this:

if (_meta != NULL) {
  // do stuff with _meta, like loop over the void*s
}

But in the constructor, I was calling one of these before setting _meta = NULL; ...

于 2013-01-02T11:36:14.050 に答える