颠倒圆形双端C的顺序

时间:2012-10-19 20:16:51

标签: c linked-list deque

好的,所以我正在进行一项任务,你必须在C中构建一个循环双端队列。我已经实现了所有的功能,我正在测试它们。一切都很好,直到'反向'功能。

我认为这很容易,你创建了一个新链接,将其连接起来代替Sentinel。杀死旧的哨兵,然后将deque的哨兵设置为新的链接。

然而,当我运行这个时,我得到一个malloc错误,因为我是C的新手,我不知道如何调试。

-------- ERROR -------

对象0x7faf13c03920的

prog(10346)malloc: * 错误:未释放指针被释放在malloc_error_break中设置断点以进行调试

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <float.h>
#include "cirListDeque.h"

/* Double Link Struture */
struct DLink {
    TYPE value;/* value of the link */
    struct DLink *next;/* pointer to the next link */
    struct DLink *prev;/* pointer to the previous link */
};

# define TYPE_SENTINEL_VALUE DBL_MAX 


/* ************************************************************************
 Deque ADT based on Circularly-Doubly-Linked List WITH Sentinel
 ************************************************************************ */

struct cirListDeque {
    int size;/* number of links in the deque */
    struct DLink *Sentinel; /* pointer to the sentinel */
};
/* internal functions prototypes */
struct DLink* _createLink (TYPE val);
void _addLinkAfter(struct cirListDeque *q, struct DLink *lnk, struct DLink *newLnk);
void _removeLink(struct cirListDeque *q, struct DLink *lnk);



/* ************************************************************************
    Deque Functions
************************************************************************ */

/* Initialize deque.

    param:  q       pointer to the deque
    pre:    q is not null
    post:   q->backSentinel is allocated and q->size equals zero
*/
void _initCirListDeque (struct cirListDeque *q) 
{
    struct DLink* lnk = (struct DLink*)malloc(sizeof(struct DLink));
    assert(lnk != 0);   //sentinel made
    q->Sentinel = lnk;
    q->Sentinel->next = q->Sentinel->prev = q->Sentinel;
    q->size = 0;
}

/*
 create a new circular list deque
 */
struct cirListDeque *createCirListDeque()
{
    struct cirListDeque* newCL = malloc(sizeof(struct cirListDeque));
    _initCirListDeque(newCL);
    return(newCL);
}


/* Create a link for a value.

    param:  val     the value to create a link for
    pre:    none
    post:   a link to store the value
*/
struct DLink * _createLink (TYPE val)
{
    struct DLink* lnk = (struct DLink*) malloc(sizeof(struct DLink));
    lnk->value = val;
    return(lnk);

}

/* Adds a link after another link

    param:  q       pointer to the deque
    param:  lnk     pointer to the existing link in the deque
    param:  newLnk  pointer to the new link to add after the existing link
    pre:    q is not null
    pre:    lnk and newLnk are not null
    post:   the new link is added into the deque after the existing link
*/
void _addLinkAfter(struct cirListDeque *q, struct DLink *lnk, struct DLink *newLnk)
{
    lnk->next->prev = newLnk;       //right connects to new
    newLnk->next = lnk->next;       //new connect to right
    newLnk->prev = lnk;             //new connect to left
    lnk->next = newLnk;             //left connect to new
    q->size++;
}

/* Adds a link to the back of the deque

    param:  q       pointer to the deque
    param:  val     value for the link to be added
    pre:    q is not null
    post:   a link storing val is added to the back of the deque
*/
void addBackCirListDeque (struct cirListDeque *q, TYPE val) 
{
    struct DLink* lnk = _createLink(val);
    _addLinkAfter(q, q->Sentinel->prev, lnk);
}

/* Adds a link to the front of the deque

    param:  q       pointer to the deque
    param:  val     value for the link to be added
    pre:    q is not null
    post:   a link storing val is added to the front of the deque
*/
void addFrontCirListDeque(struct cirListDeque *q, TYPE val)
{
    struct DLink* lnk = _createLink(val);
    _addLinkAfter(q, q->Sentinel, lnk);
}

/* Get the value of the front of the deque

    param:  q       pointer to the deque
    pre:    q is not null and q is not empty
    post:   none
    ret:    value of the front of the deque
*/
TYPE frontCirListDeque(struct cirListDeque *q) 
{
    return q->Sentinel->next->value;
}

/* Get the value of the back of the deque

    param:  q       pointer to the deque
    pre:    q is not null and q is not empty
    post:   none
    ret:    value of the back of the deque
*/
TYPE backCirListDeque(struct cirListDeque *q)
{
    return q->Sentinel->prev->value;
}

/* Remove a link from the deque

    param:  q       pointer to the deque
    param:  lnk     pointer to the link to be removed
    pre:    q is not null and q is not empty
    post:   the link is removed from the deque
*/
void _removeLink(struct cirListDeque *q, struct DLink *lnk)
{
    //assert(!isEmptyList(lst));
    lnk->next->prev = lnk->prev;    //connect right link to left link
    lnk->prev->next = lnk->next;    //connect left link to right link
    q->size--;
    free(lnk);
}

/* Remove the front of the deque

    param:  q       pointer to the deque
    pre:    q is not null and q is not empty
    post:   the front is removed from the deque
*/
void removeFrontCirListDeque (struct cirListDeque *q) {
    _removeLink(q, q->Sentinel->next);
}


/* Remove the back of the deque

    param:  q       pointer to the deque
    pre:    q is not null and q is not empty
    post:   the back is removed from the deque
*/
void removeBackCirListDeque(struct cirListDeque *q)
{
    _removeLink(q, q->Sentinel->prev);
}

/* De-allocate all links of the deque

    param:  q       pointer to the deque
    pre:    none
    post:   All links (including backSentinel) are de-allocated
*/
void freeCirListDeque(struct cirListDeque *q)
{
    while (q->size > 0){
        removeFrontCirListDeque(q);
    }
    free(q->Sentinel);
}

/* Check whether the deque is empty

    param:  q       pointer to the deque
    pre:    q is not null
    ret:    1 if the deque is empty. Otherwise, 0.
*/
int isEmptyCirListDeque(struct cirListDeque *q) {
    return q->size == 0;
}

/* Print the links in the deque from front to back

    param:  q       pointer to the deque
    pre:    q is not null and q is not empty
    post:   the links in the deque are printed from front to back
*/
void printCirListDeque(struct cirListDeque *q)
{
    struct DLink *current;
    int x = 0;
    assert(!isEmptyCirListDeque(q));

    current = q->Sentinel->next;
    while(current != q->Sentinel){
        printf("value: %f\t", current->value);
        current = current->next;
        x++;
        if (x >= 6){
            printf("\n");
            x = 0;
        }
    }
}

/* Reverse the deque

    param:  q       pointer to the deque
    pre:    q is not null and q is not empty
    post:   the deque is reversed
*/
void reverseCirListDeque(struct cirListDeque *q)
{
    //struct DLink *temp = _createNewLink(0); //try this allocat then assign then move
    struct DLink *newSent = (struct DLink*) malloc(sizeof(struct DLink));
        newSent->next = q->Sentinel->prev;
        newSent->prev = q->Sentinel->next;
        q->Sentinel->next->prev = newSent;
        q->Sentinel->prev->next = newSent;
        free(q->Sentinel);
        q->Sentinel = newSent;

/* A different approach that didn't work.
        temp->next = q->Sentinel->prev;
            q->Sentinel->prev = q->Sentinel->next;
            q->Sentinel->next = temp->next;
            free(temp);*/
}

3 个答案:

答案 0 :(得分:1)

对于调试C程序, gdb 是最好的。学习如何使用它对你有很大好处。文档位于http://sourceware.org/gdb/current/onlinedocs/gdb/

如果你真的想要一个GUI前端(并且“gdb -tui”是不可接受的),请尝试 ddd 洞察力

调试器将帮助您在程序运行时继续使用,并使您能够在每一步检查数据结构,以便在第一次损坏时找到它们。

答案 1 :(得分:0)

我调试它的方法是添加printfs。例如,在_initCirListDeque中调用malloc之后添加:

fprintf(stderr, "dbg malloc sentinel %p\n", (void *)lnk);

reverseCirListDeque中的malloc之后添加一个类似的行。

然后在_removeLinkfreeCirListDequereverseCirListDeque的免费调用之前添加类似的printf行。

当您运行代码时,您应该在标准错误上看到指针地址被malloc'd和释放。您应该能够看到未释放的值是否已经被释放(我的猜测是这就是正在发生的事情)。

单词dbg的目的是让您轻松搜索这些调试printfs并在发现错误后将其删除。

答案 2 :(得分:0)

我在这里回答了我自己的问题,但是由于这些海报,调试技巧使这个答案成为可能。

我的逻辑存在缺陷。

我认为如果你改变了哨兵的方向,你可以颠倒循环清单的顺序。但是,即使您将所有四个链接更改为标记,周围链接prev和next字段也指向错误的方向。

为了解决这个问题,我使用以下代码创建了一个新的双端队列:

    void reverseCirListDeque(struct cirListDeque *q)
{
    struct cirListDeque* newQ = createCirListDeque();
    while(!isEmptyCirListDeque(q)){
        addBackCirListDeque(newQ, backCirListDeque(q));
        removeBackCirListDeque(q);
    }
    q->Sentinel = newQ->Sentinel;
    q->size = newQ->size;
    free(newQ);
}