##
2.2.1 最終化 (finalization) と解放

        destructor tp_dealloc;

型のインスタンスの参照カウントがゼロになり、 Python インタプリタがそれを潰して再利用したくなると、 この関数が呼ばれます。解放すべきメモリをその型が保持していたり、 それ以外にも実行すべき後処理がある場合は、それらをここに入れます。 オブジェクトそれ自体もここで解放される必要があります。 この関数の例は、以下のようなものです:

    static void
    newdatatype_dealloc(newdatatypeobject * obj)
    {
        free(obj->obj_UnderlyingDatatypePtr);
        obj->ob_type->tp_free(obj);
    }

解放用関数でひとつ重要なのは、処理待ちの例外にいっさい手をつけないことです。 なぜなら、解放用の関数は Python インタプリタがスタックを元の状態に戻すときに 呼ばれることが多いからです。そして (通常の関数からの復帰でなく) 例外のために スタックが巻き戻されるときは、すでに発生している例外から解放用関数を 守るものはありません。解放用の関数がおこなう動作が追加の Python のコードを 実行してしまうと、それらは例外が発生していることを検知するかもしれません。 これはインタプリタが誤解させるエラーを発生させることにつながります。 これを防ぐ正しい方法は、安全でない操作を実行する前に処理待ちの例外を 保存しておき、終わったらそれを元に戻すことです。これは `PyErr_Fetch()`および `PyErr_Restore()`関数を使うことによって 可能になります:

    static void
    my_dealloc(PyObject *obj)
    {
        MyObject *self = (MyObject *) obj;
        PyObject *cbresult;

        if (self->my_callback != NULL) {
            PyObject *err_type, *err_value, *err_traceback;
            int have_error = PyErr_Occurred() ? 1 : 0;

            if (have_error)
                PyErr_Fetch(&err_type, &err_value, &err_traceback);

            cbresult = PyObject_CallObject(self->my_callback, NULL);
            if (cbresult == NULL)
                PyErr_WriteUnraisable();
            else
                Py_DECREF(cbresult);

            if (have_error)
                PyErr_Restore(err_type, err_value, err_traceback);

            Py_DECREF(self->my_callback);
        }
        obj->ob_type->tp_free((PyObject*)self);
    }