destructor runs even if exception in constructor

72 views
Skip to first unread message

Volker Braun

unread,
Jun 20, 2011, 7:35:40 AM6/20/11
to cython...@googlegroups.com
A simple example (below) shows that cython-0.14.1 still runs the destructor even if the constructor raised an error. This is in sharp contrast to C++ which will not run the destructor in this case. The latter makes sense because the object was never successfully constructed, so it never existed. 

Is this a deliberate design choice by Cython? I couldn't find it spelled out in the Cython docs. Or is it a bug, and the behavior might change in future versions?

>>> c = myclass()
Constructor executing
>>> del c
Destructor executing, myCptr = 0xb13500

>>> d = myclass(e=True)
Constructor executing
Destructor executing, myCptr = 0x7f9e53e642a3
*** glibc detected *** python: free(): invalid pointer: 0x00007f9e53e642a3 ***


------------------------------------------
cdef extern from "Python.h":
    char *PyString_AsString(object)

cdef extern from "string.h":
  char *strdup(char *src)

cdef extern from "stdlib.h":
  void free(void* ptr)

cdef class myclass(object):

    cdef char* myCptr

    def __cinit__(self, e=False):
        print 'Constructor executing'
        self.myCptr = <char*>"illegal value"
        if e:
            raise Exception('Some exception')
        self.myCptr = strdup(PyString_AsString('Hallo, Welt!'))
        
    def __dealloc__(self):
        print 'Destructor executing, myCptr = '+hex(<long>self.myCptr)
        free(self.myCptr)
------------------------------------------


Stefan Behnel

unread,
Jun 20, 2011, 8:26:35 AM6/20/11
to cython...@googlegroups.com
Volker Braun, 20.06.2011 13:35:

> A simple example (below) shows that cython-0.14.1 still runs the destructor
> even if the constructor raised an error. This is in sharp contrast to C++
> which will not run the destructor in this case.

Cython is not C++.


> The latter makes sense
> because the object was never successfully constructed, so it never existed.

When "__cinit__" is called, the object is *already* constructed. As the
name suggests, it's an initialisation method, not an allocation method.


> Is this a deliberate design choice by Cython? I couldn't find it spelled out
> in the Cython docs.

It's a deliberate design choice of CPython, I guess.

Regarding your specific problem: set the pointer attribute to NULL at the
beginning of "__cinit__" (and test for NULL in "__dealloc__", unless you're
really just calling free() on it).

Stefan

Reply all
Reply to author
Forward
0 new messages