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'时,我遇到了一个seg错误。我应该在使用它之后释放一个节点,对吗?那么,在这种情况下如何防止内存泄漏?有任何想法吗? 感谢。
当我删除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;
}
内存泄漏仍在发生。
答案 0 :(得分:3)
insert_queue
完成后,您还没有使用该节点。 insert_queue
例程使用temp
来保存指向节点的指针,insert_queue
在返回时使用temp
完成,但节点本身是链表的一部分,所以它正在使用中。
当remove_queue
从列表中删除节点时,您已完成节点的使用。 remove_queue
应该将指向节点的指针传递给free
以释放其内存。
不要将temp
视为节点。它只是一个临时保存指向节点的指针的对象。节点本身是一个单独的东西。
答案 1 :(得分:1)
好吧,如果您正在创建并插入新队列,为什么要删除它?请记住,当您使用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().
稍后在你的删除功能中你可以使用free删除“temp”(它实际上是使用malloc()分配的内存)。或者您可以使用free(remove_queue(&amp; myq)),它将产生完全相同的结果,因为我们正在处理指针。
答案 2 :(得分:0)
首先,“this”是在c ++中使用关键字。如果你问我,你不应该在c语境中使用它 - 只是为了避免误解。
第二个队列是指一个项目,请求,人或某物在最后排队,并且在时间(dequed)之前或之后从前面移除的东西。您似乎将此实现为链接列表,这是可以的。
下一个queue_item_t项目在堆栈上被分配为原始值的副本,因为我没有看到它是在分配给它的momory中的一个指针将在关闭时被删除}。
如果它实际上具有newQueueNode的含义,我不会调用变量temp。有意义的应用程序/类/变量/函数名称是评论代码的最佳方式之一。
在最后一条评论中,选择返回并按值传递没有ok参数,否则当你无法返回副本时会遇到问题(请参阅我的示例中的size == 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;
}