繁体   English   中英

释放C中的内存:队列

[英]Freeing memory in C: Queue

void insert_queue (queue *this, queue_item_t item) {

   //Inserts a new item at the end of queue.
   queue_node *temp = malloc(sizeof (struct queue_node));
   temp->item = item;

   if (isempty_queue(this)) this->front = temp; 
   else this->rear->link = temp;
   this->rear = temp;
   //free(temp);
}

queue_item_t remove_queue (queue *this) {
   assert (! isempty_queue (this));
   //This removes the first item from queue.
   queue_item_t temp = this->front->item;
   this->front = this->front->link;
   return temp;
}

尝试释放“ temp”时,出现段错误错误。 我应该在使用节点后释放它,对吗? 那么,在这种情况下如何防止内存泄漏? 有任何想法吗? 谢谢。

当我删除free(temp)时,一切正常,但出现内存泄漏。 如果它不属于此功能,我不确定该在哪里放。 我还添加了删除功能。 应该免费进入这里吗?

编辑:谢谢大家,这是我的更新代码。

queue_item_t remove_queue (queue *this) {
   assert (! isempty_queue (this));

   queue_node *temp = this->front;
   queue_item_t rVal = temp->item;

   //Moves on to the next one.
   this->front = this->front->link;
   //Free the unlinked node.
   //free(temp->item); <<<<---- This causes program to fail.
   free(temp);
   return rVal;
}

内存泄漏仍在发生。

insert_queue完成时,尚未完成使用节点的insert_queue insert_queue例程使用temp来保存指向该节点的指针, insert_queue返回时使用temp来完成,但是该节点本身是链接列表的一部分,因此它正在使用中。

remove_queue从列表remove_queue删除时, remove_queue可以完成节点的使用。 remove_queue应该把指针传递到节点free ,以释放内存。

不要将temp视为节点。 它只是一个临时持有指向该节点的指针的对象。 节点本身是独立的东西。

好吧,如果要创建和插入新队列,为什么要删除它? 请记住,当您使用malloc()时,您将保留一些数据,而与所在的块无关。Free()是您用来销毁使用malloc()创建的内存的工具。 所有本地作用域(不是使用malloc创建)的数据/变量都会在它们受尊重的块的末尾自动销毁。 用malloc()创建的数据在大多数情况下不会。

void insert_queue (queue *this, queue_item_t item)
{
    //Inserts a new item at the end of queue.
    queue_node *temp = malloc(sizeof (struct queue_node));
    temp->item = item;

    if (isempty_queue(this))
        this->front = temp; 
    else
        this->rear->link = temp;
    this->rear = temp;
    //free(temp);    // remember tmp is still referring to
                               // the node, so you will be erasing the
                               // node you just put inside the queue.

}     // end of code block. Variable *temp will be
      // automatically freed from memory, but
      // its malloc'd data will not. This is good
      // because its data is being used inside our
      // queue, until it is removed with remove_queue().

稍后,在您的remove函数中,您可以使用free删除“ temp”(实际上是使用malloc()分配的内存)。 或者,您可以使用free(remove_queue(&myq)),它会产生完全相同的结果,因为我们正在处理指针。

首先,“ this”使c ++中的关键字变暗。 如果您问我,也不要在c上下文中使用它-只是为了避免误解。

其次,队列是指某个项目,请求,人员或某物在末尾排队,并在有时间(充足)的时间从前部或稍后移出的东西。 您似乎将其实现为链接列表,没关系。

下一个queue_item_t项将作为原始值的副本分配到此处的堆栈中,因为我看不到它是分配在其内存中的指针,将在结束}时删除。

如果它实际上具有诸如newQueueNode之类的含义,我就不会称其为变量temp。 有意义的应用程序/类/变量/函数名是注释代码的最佳方法之一。

在最后的注释中,选择的返回值和没有ok参数的值传递,否则在无法返回副本时会遇到问题(有关大小== 0,请参见我的示例),并且无法告诉用户出现错误的功能(在这种情况下,队列为空)

这是我(快速生产和测试)的最小问题解决方案:

#include <stdlib.h>
#include <stdio.h>

struct queue_item_t
{
    int exampleItemData;
};

struct queue_node
{
    struct queue_item_t *item;
    struct queue_node *next;
};

struct queue
{
    struct queue_node *firstItem;
    struct queue_node *lastItem;
    int size;
};


struct queue* createQueue()
{
    struct queue *queuePtr = (struct queue *)malloc(sizeof (struct queue));
    queuePtr->firstItem = NULL;
    queuePtr->lastItem = NULL;
    queuePtr->size = 0;
    return queuePtr;
}

void queue(struct queue* queueData, struct queue_item_t itemToQueue)
{
    // Create new node
    struct queue_node* newNode = (struct queue_node*)malloc(sizeof(struct queue_node));

    // Create new item
    newNode->item = (struct queue_item_t*)malloc(sizeof(struct queue_item_t));

    // Copy the item data from itemToQueue that will be deleted on the end of this function
    newNode->item->exampleItemData = itemToQueue.exampleItemData;

    // Insert the item into the queue
    if(0 == queueData->size)
    {
        queueData->firstItem = newNode;
        queueData->lastItem = newNode;
        newNode->next = newNode;
    }
    else
    {
        queueData->lastItem->next = newNode;
        queueData->lastItem = newNode;
    }

    queueData->size += 1;

    // ! itemToQueue will deleted here we must have a copy of the data in the queue }
}

struct queue_item_t dequeue(struct queue* queueData)
{
    struct queue_item_t item;

    if (1 > queueData->size)
    {
        // !!! Serious problem if this happens:
        // What will you return, an initialized queue_item_t?
        // You can not return a null pointer ...
        // Better you write ok to a boolean comming in ass parameter or something
    }
    else if(1 == queueData->size)
    {
        item.exampleItemData = queueData->firstItem->item->exampleItemData;

        free(queueData->firstItem->item);
        free(queueData->firstItem);
        queueData->firstItem = NULL;
        queueData->lastItem = NULL;
    }
    else if(2 == queueData->size)
    {
        item.exampleItemData = queueData->firstItem->item->exampleItemData;

        struct queue_node* dequeuedNode = queueData->firstItem;
        queueData->firstItem = dequeuedNode->next;
        queueData->lastItem = dequeuedNode->next;
        free(dequeuedNode->item);
        free(dequeuedNode);
    }
    else if (1 < queueData->size)
    {
        item.exampleItemData = queueData->firstItem->item->exampleItemData;

        struct queue_node* dequeuedNode = queueData->firstItem;
        queueData->firstItem = dequeuedNode->next;
        free(dequeuedNode->item);
        free(dequeuedNode);
    }

    queueData->size -= 1;

    return item;
}


int main() {
    struct queue* myQueue = createQueue();
    struct queue_item_t item;
    item.exampleItemData = 665;
    queue(myQueue, item);

    item.exampleItemData = 666;
    queue(myQueue, item);

    item.exampleItemData = 667;
    queue(myQueue, item);

    for(int i = myQueue->size; i > 0; --i)
    {
        struct queue_item_t dequeuedItem = dequeue(myQueue);
        printf("Dequed ITem data = %i\n",  dequeuedItem.exampleItemData);
    }

    // Now the next shows an undefined state if someone dequeues with size 0 or smaller:
    struct queue_item_t dequeuedItem = dequeue(myQueue);
    printf("Dequed ITem data = %i\n",  dequeuedItem.exampleItemData);

    // I recommend using a boolean like mentioned above

    return 0;
}

暂无
暂无

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

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