Segfault after deepcopy in a C extension

Marco Sulla Marco.Sulla.Python at gmail.com
Mon Jan 31 16:52:57 EST 2022


Well, this is more or less what I'm trying to do.

I have an immutable object. I would have copy.deepcopy() will return the
object itself if it's hashable. If not, it must return a deepcopy of it.

So I tried to implement a __deepcopy__ for the object. It segfaults if the
object is not hashable. And I don't understand why. gdb gives me an
incomprehensible backtrace. So I tried the old "print at each line", but
the segfault does not happen in the function. It happens when I quit REPL
or if I try to see the deepcopy.

What can I do to further debug it?

If someone is interested, this is the code:

PyObject* frozendict_deepcopy(PyObject* self, PyObject* memo) {
    if (PyAnyFrozenDict_CheckExact(self)) {
        frozendict_hash(self);

        if (PyErr_Occurred()) {
            PyErr_Clear();
        }
        else {
            Py_INCREF(self);
            return self;
        }
    }

    if (! PyAnyFrozenDict_Check(self)) {
        Py_RETURN_NOTIMPLEMENTED;
    }

    PyObject* d = PyDict_New();

    if (d == NULL) {
        return NULL;
    }

    PyObject* copy_module_name = NULL;
    PyObject* copy_module = NULL;
    PyObject* deepcopy_fun = NULL;
    PyObject* args = NULL;
    PyObject* res = NULL;

    if (PyDict_Merge(d, self, 1)) {
        goto end;
    }
    copy_module_name = PyUnicode_FromString("copy");

    if (copy_module_name == NULL) {
        goto end;
    }

    copy_module = PyImport_Import(copy_module_name);

    if (copy_module == NULL) {
        goto end;
    }

    deepcopy_fun = PyObject_GetAttrString(copy_module, "deepcopy");

    if (deepcopy_fun == NULL) {
        goto end;
    }

    args = PyTuple_New(2);

    if (args == NULL) {
        goto end;
    }

    PyTuple_SET_ITEM(args, 0, d);
    PyTuple_SET_ITEM(args, 1, memo);

    res = PyObject_CallObject(deepcopy_fun, args);

end:
    Py_XDECREF(args);
    Py_XDECREF(deepcopy_fun);
    Py_XDECREF(copy_module);
    Py_XDECREF(copy_module_name);
    Py_DECREF(d);

    return res;
}


More information about the Python-list mailing list