Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
112 views
in Technique[技术] by (71.8m points)

c++ - I can't get __dealloc__ be called when deleting an object

I have the following C++ class :

.H

class ALabSet: public LabSet {
public:
    PyObject *m_obj;

    ALabSet(PyObject *obj);

    virtual ~ALabSet();

    PyObject *GetPyObj();

};

.CPP

ALabSet::ALabSet(PyObject *obj): LabSet() {

    this->m_obj = obj;
    // Provided by "cyelp_api.h"
    if (import_cyelp()) {
    } else {
        Py_XINCREF(this->m_obj);
    }

}


ALabSet::~ALabSet() {
    Py_XDECREF(this->m_obj);
}


PyObject *ALabSet::GetPyObj() {
    return this->m_obj;
}

I exposed it as follows with Cython :

cdef extern from "adapter/ALabSiteSetsManager.h" namespace "elps" :
    cdef cppclass ALabSet:
        ALabSet(PyObject *)

        PyObject *GetPyObj()



cdef class PyLabSet:
    cdef ALabSet *thisptr

    def __cinit__(self):
       self.thisptr = new ALabSet(<PyObject *>self)

    def __dealloc__(self):
       print "delete from PY !"
       if self.thisptr:
           del self.thisptr

My problem is that I can't figure out how to get the destructor called from Python. The following does exactly nothing :

a_set = PyLabSet()
del a_set

I can't find similar issues on the web. Does any of you has an idea of is appening to me here ?

I'm I missing something about reference counting management, or ...

Thanks a lot

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

del a_set removes a reference to the object (the local variable). There's still another reference, in the C++ object. This is known as a reference cycle. The cycle GC could collect this after a while. However, there is no guarantee when (or even if) this happens, so you should not rely on it1.

For example, reference cycles containing pure Python objects with a __del__ special method are documented to not be freed at all:

Changed in version 3.4: Following PEP 442, objects with a __del__() method don’t end up in gc.garbage anymore.

I don't know whether Cython's implementation of __dealloc__ triggers this behavior, but as outlined before, destruction isn't deterministic anyway. If you want to free some resource (e.g. a block of memory that isn't a Python object, a file, a connection, a lock, etc.) you should expose an explicit way of doing so manually (cf. the close methods of various objects). Context managers can simplify client code doing this.

Disclaimer: Almost all of this is CPython-specific.

1 Some people prefer thinking of GC as an abstraction that simulates availability of infinite memory, rather than something that destroys unreachable objects. With this approach, it becomes quite obvious that destruction is not deterministic and not even guaranteed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...