解除引用void **参数时的Segfault

时间:2017-02-08 21:40:31

标签: c pointers void-pointers

我对这里的指针缺乏了解。 foo1 foo 类型的指针。在dequeue中,有一个由 foo 类型的项目列表,这些项目由queueList传递。我的任务是让 foo1 指向队列的头部,然而,访问传递给 dequeue() foo1 指针 * data 会导致段错误。这是我缺乏理解的地方。 *数据不是指 foo1 指针吗?

struct foo
{
//Properties Here
};

int main()
{
    struct foo* foo1;
    dequeue(myQueueList, (void*) foo1);
}

void dequeue(struct queue* queueList, void **data)
{
    *data = NULL; //Causes Seg fault if I do this too
    *data = queueList->head->data; //Seg fault if I do this as well
    return;
}

我的队列定义为:

struct queue
{
    node * head;
    //other stuff
};

struct node
{
    void * data;
    //other stuff
};

编辑:foo1未在main中初始化。我希望通过将其设置为等于已入队的不同struct foo *指针来将其初始化。

Edit2:queue包含struct foo *指针的列表。

Edit3:感谢wildplasser,它已修复为(void *)foo1 - > (无效*)及foo1。但为什么我必须使用& foo1而不是(void *)?

1 个答案:

答案 0 :(得分:2)

在此代码中:

struct foo* foo1;
dequeue(myQueueList, (void*) foo1);

表达式(void *)foo1导致未定义的行为,因为您使用了未初始化指针的值。

您想要做的概念是将 foo1地址传递给函数,以便函数可以修改foo1。您需要&运算符来查找事物的地址。

但是该功能对struct foo *一无所知。 void **不是通用指针类型;它是指向void *的指针,而不是其他任何指针。因此,为了使此代码无需更改dequeue的定义,您需要创建void *变量:

void *vfoo;
dequeue(myQueueList, &vfoo);
struct foo *foo1 = vfoo;

如果你可以改变它的设计,那么使用dequeue会更容易;特别是让它返回void *。然后你可以写struct foo *foo1 = dequeue(myQueueList);

注意:在评论中建议使用dequeue(myQueueList, (void **)&vfoo);,但是由于严格的别名冲突,这会导致未定义的行为。无法通过struct foo *类型的左值访问类型void *的对象。