2

我正在尝试为 python 编写一个 C 扩展。这个扩展基本上只是一个双链表。

以下是我编写的代码中的部分内容:-

staticforward PyTypeObject linked_list_type;

typedef struct _linked_list_object{
    PyObject_HEAD
    int val;
    struct _linked_list_object *prev;
    struct _linked_list_object *next;
} linked_list_object;

//this method adds a new node to the linked list
static linked_list_object* add_node(linked_list_object * obj, int val)
{
    linked_list_object* new;

    new = PyObject_New(linked_list_object, &linked_list_type);
    if (new){
        new->val = val;
        if (obj)
        {
            new->prev = obj;
            new->next = obj->next;
            obj->next = new;
            new->next->prev = new;
        }
        else{
            new->next = new;
            new->prev = new;
        }
        return new;
        }
        else
        {
        return NULL;
        }

在我编译这个模块并将其导入 python 之后。

该代码引发分段错误。

>>> import linked_list
Segmentation fault: 11 (core dumped)

我注意到如果我注释掉,则不会生成此分段错误

new = PyObject_New(linked_list_object, &linked_list_type);

以及它下面的代码。

有人可以帮我解释为什么会发生这种分段错误。?

我知道我错过了一些东西,但我无法弄清楚它是什么。

4

1 回答 1

2

根据Python 文档中的这个示例,我认为问题在于您没有提供完全初始化的linked_list_type。

在该示例中 noddy_NoddyType 等同于您的代码中的linked_list_type,您将在顶部看到它们:

staticforward PyTypeObject noddy_NoddyType;

像你所做地。

然而,他们有:

static PyTypeObject noddy_NoddyType = {
    PyObject_HEAD_INIT(NULL)
    0,
    "Noddy",
    sizeof(noddy_NoddyObject),
    0,
    noddy_noddy_dealloc, /*tp_dealloc*/
    0,          /*tp_print*/
    0,          /*tp_getattr*/
    0,          /*tp_setattr*/
    0,          /*tp_compare*/
    0,          /*tp_repr*/
    0,          /*tp_as_number*/
    0,          /*tp_as_sequence*/
    0,          /*tp_as_mapping*/
    0,          /*tp_hash */
}; 

正如示例所解释的那样,PyObject_New 使用设置为 sizeof(noddy_NoddyObject) 的成员来了解要为新对象分配多少内存。我相信 staticforward 是一个变成静态的宏,这意味着

staticforward PyTypeObject linked_list_type;

将创建所有字段初始化为零,因此 PyObject_New 将尝试为您的新对象分配 0 个字节。因此,访问该对象的任何字段都涉及访问您不拥有的内存,结果是分段错误。

于 2013-04-13T10:59:33.223 回答