繁体   English   中英

C程序分段错误

[英]C Program Segmentation Fault

我很难在一个类项目的代码中找到分段错误(这部分是未分级的)。 我正在为OS类实现队列,并且在add函数中遇到段错误。

void AddQueue(QElem * head, QElem * item) {
    printf("WHERE\n");
    if(head == NULL){
        printf("THE\n");
        head = item;
        //item->next = item;
        //item->prev = item;
    }
    else{
        printf("$^&*\n");
        (head->prev)->next = item;
        printf("ARE\n");
        item->prev = (head->prev);
        printf("YOU\n");
        item->next = head;
        printf("FAILING\n");
        head->prev = item;
    }
    printf("!?!?!?\n");
}

我有一个Test函数,我正在从另一个类中调用...

void TestAddQueue()
{
    printf("********************************************\n");
    printf("Begin testing the add test function\n");
    printf("********************************************\n");

    QElem * queue;
    InitQueue(queue);


    for(int i = 0; i < 10; i++)
    {
        printf("Adding element %d\n", i+1);
        QElem * newElem = NewItem();
        printf("Changing payload value\n");
        newElem->payload = i+100;
        printf("Adding to the queue\n");
        AddQueue(queue, newElem);
        printf("Item added, payload value = %d\n", queue->payload);
        printf("The previous payload = %d\n", queue->prev->payload);

    }
    for(int i = 0; i < 10; i++)
    {
        printf("Rotating list", i+1);
        RotateQ(queue);
        printf("Printing element %d\n", i+1);
        printQElem(queue);
    }
}

这是NewItem函数...

QElem * NewItem()
{
    // just return a new QElem struct pointer on the heap
    QElem * newItem = calloc(1,sizeof(QElem));
    newItem->next = newItem;
    newItem->prev = newItem;
    newItem->payload = -1;
    return newItem;
}

...这是运行程序的输出...

********************************************
Begin testing the add test function
********************************************
Adding element 1
Changing payload value
Adding to the queue
WHERE
THE
!?!?!?
Segmentation fault

现在,传递给add函数的头指针应该为NULL,因为它发送给初始化函数,该函数只将指针的值设置为NULL,所以我认为这不会引起我的问​​题。

我的猜测是,以下一行是导致问题的原因...

printf("Item added, payload value = %d\n", queue->payload);

可能当我尝试获取有效载荷值时,或者我尝试访问的结构不再存在,或者以某种方式将队列指针移至无效空间。 在正确的方向上的任何反馈或推动将不胜感激。

旁注:这是在Unix服务器环境(bash)中编译的,目前,我无权访问IDE来调试和查看变量。

在C语言中,参数按值传递,这意味着它们已被复制 当然,更改副本不会更改原始文档。

因此,在AddQueue函数中,变量head是一个副本 ,您可以根据需要进行任意更改,您最初传递给该函数的变量将完全不会更改。

为了能够更改参数,您需要按引用传递 ,C没有该引用 ,但是可以使用指针对其进行仿真。 当然,这意味着要通过引用传递指针,必须将指针传递给指针。


因此对于您的代码来说

void AddQueue(QElem ** head, QElem * item) {
    if(*head == NULL){
        *head = item;
    }
    ...
}

...

AddQueue(&queue, newElem);

什么上述变化做的是首先使AddQueue采取指针的指针QElem ,从而模拟传递通过引用成语。 要使用原始指针,请使用解引用运算符* ,该运算符为您提供指针所指向的值(在本例中为原始指针)。 然后要将指针实际传递给指针,必须在指针变量上使用地址操作符&

head = itemAddQueue函数外部的AddQueue没有任何影响。 如果将空指针作为head传递给AddQueue ,则在AddQueue完成后,该指针仍将为null。

感谢@Joachim,我得以按预期运行队列。 参见下面的重构代码。

首先添加功能...

////////////////////////////////////////////////////////////////////////////////
//
//  Add Queue
//
//      Adds a queue item, pointed to by `item`, to the end of the queue pointed
//      to by `head`.
//
//      Note: Tested 2-12-2015 using proj_1.c tests. PASSED -Dave
//
////////////////////////////////////////////////////////////////////////////////
int AddQueue(QElem ** head, QElem ** item) {

    //If the queue is empty...
    if(*head == NULL){
        //Point the head to the item.  The new item's next/prev were initialized
        //to point to itself already.
        *head = *item;
    }
    //If there are already elements in the queue...
    else{
        // insert the new element at the end of the list (just to the left
        // of the head) setting the next and previous values of the
        // appropriate nodes to the new values.
        ((*head)->prev)->next = *item;
        (*item)->prev = ((*head)->prev);
        (*item)->next = *head;
        (*head)->prev = *item;
    }
    return TRUE;
}

接下来的新项目功能...

////////////////////////////////////////////////////////////////////////////////
//
//  New Item
//
//      Returns a pointer to a new queue element created in heap memory.
//
//      Note: Calloc is a more precise way of allocating, but is basically the
//      same as malloc, the 1 denotes how many of the item to reserve mem for.
//      -Dave
//
//      Note: Tested 2-12-2015 using proj_1.c tests. PASSED -Dave
//
////////////////////////////////////////////////////////////////////////////////
QElem * NewItem()
{
    // just return a new QElem struct pointer on the heap with values initialized
    QElem * newItem = calloc(1,sizeof(QElem));
    newItem->next = newItem;
    newItem->prev = newItem;
    newItem->payload = -1;
    return newItem;
}

现在为测试添加功能...

////////////////////////////////////////////////////////////////////////////////
//
//  A test function for the add function.  It will create a queue of items
//  and attempt to iterate through them and print the value of the payload
//
////////////////////////////////////////////////////////////////////////////////
void TestAddQueue(QElem ** queue){
    printf("********************************************\n");
    printf("Begin testing the add test function\n");
    printf("********************************************\n");

    InitQueue(&(*queue));

    for(int i = 0; i < 10; i++)
    {
        printf("Adding element %d\n", i+1);
        QElem * newElem = NewItem();
        printf("Changing payload value\n");
        newElem->payload = i+100;
        printf("Adding to the queue\n");
        AddQueue(&(*queue), &newElem);
        printf("Item added, payload value = %d\n", newElem->payload);
        printf("The previous payload = %d\n", (*queue)->prev->prev->payload);

    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM