【发布时间】:2015-06-21 09:51:55
【问题描述】:
我已经阅读了几个针对类似问题给出的答案,但有一件事使我的案例与我所阅读的内容略有不同。我使用链表来存储数据,以供线程选择和处理。一个节点就是一个简单的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 指针而无需任何分段不能依赖错误。所以问题基本上是我做对了还是我的担忧真的合理?如果这确实可能导致内存泄漏或其他与内存相关的问题,我该怎么做?
【问题讨论】:
-
使用您显示的代码,您可以释放新的
head指针。不要免费node->next。 -
struct QueueNode在整个代码中是一个不完整的类型...也许是一个无关紧要的错误,但仍然是一个错误,尤其是当您尝试取消引用next成员时。我可以建议在typedef struct之后直接插入QueueNode吗? -
实际代码中实际上定义为
typedef struct QueueNode {...,但我很欣赏这个注释。 -
一般来说,对结构进行类型定义是个坏主意。对结构进行类型定义只会弄乱代码,弄乱编译器名称空间,并且在维护代码时(可能是几年后)可能会导致误解。
-
@user3629249 你能详细说明一下吗?到目前为止,我看到的每个教程都显示类型定义结构是正常的。