我已经阅读了几个类似问题的答案,但有一件事使我的案例与我读过的略有不同。我使用链表来存储要挑选和处理的线程的数据。节点是一个简单的typedef
struct QueueNode;
typedef struct QueueNode {
struct QueueNode* next; // pointer to the next node
void* data;
} QueueNode;
列表
typedef struct LinkedQueue {
QueueNode* head; // pointer to the first Node
QueueNode* tail; // pointer to the last Node
long long k; // the number of nodes in the queue
} LinkedQueue;
两者都由使用malloc
的相应函数初始化。当一个线程需要处理数据时,它会调用一个弹出队列头部并返回void* data
指针的函数。
void* pop_data(LinkedQueue* queue) {
/*
Pops the head node from a queue, extracts data out of it and
frees the memory allocated by that node
*/
assert(queue->head && "Can't pop data from an empty queue");
void* data = queue->head->data; // extract data from head
QueueNode* old_head_pointer = queue->head;
queue->head = queue->head->next; // replacing head with a new one
destroy_node(old_head_pointer); // destroying the old head
return data;
};
问题是destroy_node
应该释放为节点分配的内存而不破坏void* data
指针,因为稍后会使用这些数据。这是我的情况变得与众不同。我已经阅读过的所有示例都描述了一个完全释放节点内部所有内容的情况,而我需要保存一个指针。
void destroy_node(QueueNode* node) {
/*
Frees memory allocated by a node.
*/
free(node->next);
free(node);
};
在我的测试中,这很好用,但是因为我知道free()
实际上并没有擦除内存,因为我的机器有大量的内存,我仍然可以访问void* data
没有任何分段错误的指针不能依赖。所以问题基本上是我做得对吗还是我的担忧真的合理吗?如果这确实可能导致内存泄漏或其他与内存相关的问题,我该怎么做呢?
答案 0 :(得分:3)
你做得对,因为你在释放整个节点之前访问data
指针。反过来会是一个逻辑错误。
如果您实际在代码中的某个地方释放数据,则不会发生内存泄漏。
但是,您应该不释放节点的next
字段,因为它会使该节点无效,这可能不是您想要做的。
答案 1 :(得分:0)
如果您想将指针保持在'数据',
然后在调用' destroy_node()'
之前将该指针保存到局部变量中destroy_node()函数对' void * Data'的内存没有任何影响。指着。
正如其他地方所述,不要随意()下一个'指针,因为它实际上释放了链表中的下一个节点(其中' head'只是设置为指向)
这意味着' head'现在指向未分配的内存。
对该未分配内存的任何引用都会导致未定义的行为。
未定义的行为可能导致任何事情,包括seg故障事件。
所有编译操作都应在启用大多数/所有警告的情况下执行。
启用警告后,发布的代码将引发2个警告。
每个警告都说:
ISO C does not allow extra ';' outside of a function